【Offer】[23] 【链表中环的入口结点】
题目描述
一个链表中包含环,如何找出环的入口结点?


思路分析
- 判断链表中是否有环:用快慢指针的方法,慢指针走一步,快指针走两步,如果快指针追上了慢指针,就说明有环,而且他们相遇的节点是处于环中的节点
- 统计环中节点的个数:利用1中返回的节点,当再次走到该节点时,正好遍历了整个环,从而可以统计出个数n。
- 找出入口结点:也是设置两个指针,第一个指针先向后移动n,第二个指针指向头节点,然后同时移动两个指针,它们相遇时的节点就是环的入口节点,(类似于 【链表中倒数第k个结点】 中的思路)
测试用例
- 功能测试:链表中包含或者不包含环;链表中有多个或者只有一
节点。 - 特殊输入测试:链表头节点为nullptr指针。
Java代码
public class Offer23 {
public static void main(String[] args) {
test1();
test2();
test3();
test4();
test5();
}
public static ListNode EntryNodeOfLoop(ListNode head) {
return Solution1(head);
}
/**
* 1.判断链表中是否有环,并找出环中节点个数n 2.将一个指针向前移动n,另个一指针指向头节点 3. 然后同时移动两个指针,两个指针相遇时,就是环的入口
*
* @param head
* @return
*/
private static ListNode Solution1(ListNode head) {
if (head == null) {
return null;
}
// 判断链表中是否有环,并找到快慢指针相遇的节点
ListNode meetNode = MeetingNode(head);
if (meetNode == null) {// 说明链表中没有环
return null;
}
int count = 1; // 统计环中节点的个数
ListNode pLoop = meetNode;
while (pLoop.next != meetNode) {
pLoop = pLoop.next;
++count;
}
ListNode p1 = head;
for (int i = 0; i < count; i++) {
p1 = p1.next;
}
ListNode p2 = head;
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
/**
* 设置两个指针,快指针一次走两步,慢指针一次走一步 如果快指针 追上了慢指针,就说明有环
* 如果快指针走到尾部(null)时两个指针没有相遇,就说明两个指针没有环存在,
*
* @param head
* @return
*/
private static ListNode MeetingNode(ListNode head) {
if (head == null) {
return null;
}
ListNode pSlow = head.next;
if (pSlow == null) {
return null;
}
ListNode pFast = pSlow.next;
while (pSlow != null && pFast != null) {
if (pSlow == pFast) {
return pFast;
}
pSlow = pSlow.next;
pFast = pFast.next;
if (pFast != null) {
pFast = pFast.next;
}
}
return null;
}
private static void test1() {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
ListNode node6 = new ListNode(6);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
node6.next = node3;
System.out.println("链表中有环而且有多个节点(>=3)---->");
ListNode entryLoop = EntryNodeOfLoop(node1);
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("null");
}
}
private static void test2() {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
ListNode node6 = new ListNode(6);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
System.out.println("链表中没有环---->");
ListNode entryLoop = EntryNodeOfLoop(node1);
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("null");
}
}
private static void test3() {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
node1.next = node2;
node2.next = node1;
ListNode entryLoop = EntryNodeOfLoop(node1);
System.out.println("链表中有环,只有有两个个节点---->");
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("null");
}
}
private static void test4() {
ListNode node1 = new ListNode(1);
node1.next = node1;
ListNode entryLoop = EntryNodeOfLoop(node1);
System.out.println("链表中有环,只有一个节点---->");
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("没有环");
}
}
private static void test5() {
ListNode entryLoop = EntryNodeOfLoop(null);
System.out.println("传入null---->");
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("null");
}
}
}
代码链接
【Offer】[23] 【链表中环的入口结点】的更多相关文章
- 【Java】 剑指offer(23) 链表中环的入口结点
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中, ...
- 【剑指Offer】链表中环的入口结点 解题报告(Python)
[剑指Offer]链表中环的入口结点 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews ...
- 剑指offer:链表中环的入口结点
题目描述: 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 思路分析: 这道题首先需要判断链表是否存在环,很快就能想到用快慢指针来判断. 由于快慢指针的相遇位置并不一定为链 ...
- Go语言实现:【剑指offer】链表中环的入口结点
该题目来源于牛客网<剑指offer>专题. 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. Go语言实现: /** * Definition for sing ...
- 剑指Offer 55. 链表中环的入口结点 (链表)
题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 题目地址 https://www.nowcoder.com/practice/253d2c59ec3e4bc68d ...
- [剑指Offer] 55.链表中环的入口结点
题目描述 一个链表中包含环,请找出该链表的环的入口结点. [思路]根据set集合的不重复,遍历链表时遇到的第一个重复结点就是环的入口结点. /* struct ListNode { int val; ...
- 剑指Offer:链表中环的入口节点【23】
剑指Offer:链表中环的入口节点[23] 题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 题目分析 第一步确定链表中是否包含环,怎么确定呢?我们定义两个指针橙和 ...
- 《剑指offer》第二十三题(链表中环的入口结点)
// 面试题23:链表中环的入口结点 // 题目:一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中, // 环的入口结点是结点3. #include <iostream> ...
- 链表中环的入口结点 牛客网 剑指Offer
链表中环的入口结点 牛客网 剑指Offer 题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. # class ListNode: # def __init__(se ...
- 【剑指offer】面试题 23. 链表中环的入口节点
面试题 23. 链表中环的入口节点
随机推荐
- lvs+keepalived 高可用及负载均衡
一.环境准备 VIP:10.18.43.30 dr1:10.18.43.10 dr2:10.18.43.20 web1:10.18.43.13 web2:10.18.43.14 结构图 (一).预处理 ...
- 夯实Java基础(一)——数组
1.Java数组介绍 数组(Array):是多个相同类型元素按一定顺序排列的集合. 数组是编程中最常见的一种数据结构,可用于存储多个数据,每个数组元素存放一个数据,通常我们可以通过数组元素的索引来访问 ...
- Spark 系列(五)—— Spark 运行模式与作业提交
一.作业提交 1.1 spark-submit Spark 所有模式均使用 spark-submit 命令提交作业,其格式如下: ./bin/spark-submit \ --class <ma ...
- HelloDjango 第 07 篇:创作后台开启,请开始你的表演!
作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 在此之前我们完成了 django 博客首页视图的编写,我们希望首页展示发布的博客文章列 ...
- Spark 系列(十五)—— Spark Streaming 整合 Flume
一.简介 Apache Flume 是一个分布式,高可用的数据收集系统,可以从不同的数据源收集数据,经过聚合后发送到分布式计算框架或者存储系统中.Spark Straming 提供了以下两种方式用于 ...
- SAP Special Fields in FAGLL03 transaction
https://wiki.scn.sap.com/wiki/display/ERPFI/Special+Fields+in+FAGLL03+transaction https://wiki.scn.s ...
- unsqueeze 和 squeeze
squeeze压缩的意思 就是在第几维为1 去掉 unsqueeze 解缩 在第几维增加 变成*1 squeeze用法 c = b.view(1, 1, 1, 2, 3) c.squeeze(0) # ...
- 常用的python内置方法
all ( ) 循环参数,参数全为真就返回Ture any() 只要有一个 ...
- Redis 学习笔记(篇九):主从复制
Redis 中,可以通过执行 savleof 命令或者设置 slaveof 选项,让一个服务器去复制另一个服务器,我们称被复制的服务器为主服务器,而对主服务器进行复制的服务器则被称为从服务器. Red ...
- 程序与CPU
CPU中共有四大组件: 寄存器 控制器 运算器 时钟 寄存器:存取数值(存东西的) 控制器:负责将内存(寄存器)中的数据进行读入和写出(控制寄存器 协调者) 运算器:里面是逻辑运算单元,协助寄存器和控 ...