文章目录
- 题目详情
- 分析
- Java完整代码
题目详情
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
分析
本题是leetcode141. 环形链表的升级问题,可以先通过leetcode141_环形链表这篇博客了解环形链表的基础问题解决方法。
这里假设,已经知道可以通过快慢指针判断链表是否存在循环的情况,如果不清楚为什么使用快慢指针,可以先看一下上面链接的博客。
在这里提出一个有意思的想法,我们在解决问题的时候,有的时候可能需要通过观察推理规律的方法。比如本题目。
我们已经知道一个循环链表,使用快慢指针可以判断出链表存在环,可是我们需要寻找入环点,一开始可能有点懵,这怎么解决啊,别急,让我们看看下图,一看就清楚了。
如图上推导过程所示,以快慢指针相遇点为开始点同链表起点一起遍历,当两者相等时,就是入环点。
图中的s,f分别为慢,快指针,下标表示第几次的一个状态情况。
注意:有的时候遇到问题,需要通过观察规律并推导一下就能解决,所以可以在草稿上多画画。
详情请看代码。
Java完整代码
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
// head为空,或者head.next为空
if (head==null || head.next == null || head.next.next == null) {
return null;
}
ListNode s = head.next;
ListNode f = head.next.next;
while (s != f) {
if (f.next == null || f.next.next == null) {
// 直接返回,为空代表没有环
return null;
}
f = f.next.next;
// 对于s不用判断,因为f更快
s = s.next;
}
// 出while循环,即为有循环,并且此时的f=s
ListNode p = head;
while(p != f) {
p = p.next;
f = f.next;
}
// 出这个while循环,表示相遇点就是入链表循环的位置
return p;
}
}