142. 环形链表 II
不是很难。
就是看看有没有环,有的话,就进去就行了。
首先通过fast!=null && fast.next!=null判断是否有环。如果有环一定是fast == slow的。
如果没环,那跑出来可能是fast == null或者是fast.next == null。这取决于链表中节点的个数。
如果是偶数个节点:· · · ·
,那fast首先在 0 处,然后跑到 2 处,然后是 4 处(4是空,所以是fast == null)
如果是奇数个节点:· · · · ·
,那fast首先在 0 处, 然后在 2 处, 然后在 4 处,此时fast.next=null。
以上是判断是否没环。
如果有环,一定是fast=slow。
如果是fast==slow,那就需要找到环的入口。
这部分考研时候学过:
设从原点到环入口长度为a,环的长度为r,环入口到相遇点的距离为x,则当slow到相遇点时,fast已经在环里饶了n圈了
则根据t1=t2 -> a+x / 1 = a+x+nr / 2 得出2(a+x)=a+x+nr,即a=nr-x.则设置两个指针,一个从原点出发,
一个从相遇点出发,两个指针同步移动,经过若干次循环后一定能在起点相遇。
eg. n = 1时,a=r-x,r-x就是在环里要走的剩余的长度,a就是从原点到相遇点的距离,则正好在环入口相遇*/
直接做就行了
/**
* 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) {
if(head == null) return null;
ListNode fast = head, slow = head;
while(fast!=null && fast.next!=null) {
System.out.println("fast=" + fast.val + " slow=" + slow.val);
fast = fast.next.next;
slow = slow.next;
if(slow == fast)
break;
}
// fast == null表示偶数个然后走到头了,fast.next==null表示奇数个走到头了
// · · · ·
// · · · · ·
if(fast==null || fast.next == null) return null;
// 有环 成功进入了
if(fast == slow) {
slow = head;
while(slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
return null;
}
}