Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Note: Do not modify the linked list.
(这道题做错了太多遍,又没有test cases,实在蛋疼。)自己之前的想法一直是错误的。直到上网查了其他人的算法,才明白,惭愧哎。
思路:1. 和之前差不多,依然有fast指针和slow指针。
2. 假设入圈之前的长度是L,入圈之后的长度分为a+b. 他们第一次相遇的地点则是在L+a
3. 他们第一次相遇时,slow走过的长度是L+a, 则fast实际走过了2L+2a. 毕竟相遇时,fast肯定是比slow多走过一个a+b的长度的。所以 (2L+2a) - (L+a) = L + a = a + b
所以我们可以得到一个很重要的结论: L = b !!
4. 若想得知起始点,让他们在此相遇就好了,也就是说,他们之间的距离差依然需要是圆圈的整数倍。所以接下来他们走的步数一致的话,则距离差不会变,依然是圆圈的 整数倍。所以首先,接下来我们需要调整他们的步数。让他们步数一致。
5. 再考虑起步点。fast和slow肯定是要从不同点起始的。不然步数一致的话,就永远都在一起了。fast现在所在位置是L+a,只需再行进b,就可到达圆圈起始点。由于b=L, 我们知道,slow再行进L 或b,就也可以到达起始点。以防他们在起始点之前相遇,所以选择让slow节点从head开始,行进L,则刚好可以相遇在圆圈的起始点。
思路写下来,依然觉得有从结论倒推命题的感觉。可能是理解得依然不够透彻。以后有时间再多想想好了。
代码依然写的很烂=。=
/**
* 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) {
ListNode fast = head;
ListNode slow = head;
if(head == null || head.next == null)
return null;
int count = 0;
int first = 0;
while(fast.next != null && fast != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
count++;
if(slow == fast){
first = count;
break;
}
}
if(fast.next == null || fast.next.next == null || fast == null)
return null;
if (slow == fast){
slow = head;
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return slow;
}
return null;
}
}