Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Follow up:
Can you solve it without using extra space?
思路:
做过,就当复习了。
先用快慢指针判断相交,关键是环开始点的获取。
用上图说明一下,设非环的部分长度为a(包括环的入口点), 环的长度为b(包括环的入口点). 快慢指针相交的位置为绿色的点,距离环的开始位置为c(以环的入口点距离为0算)。
因为快指针的速度是慢指针的两倍。 故: a + f*b + c = 2(a + s*b + c)
得出: a + c = k * b
即此时一个指针从相交点开始走,距离入口为c, 再走一个a的距离 就会到达入口点,也就是说从相交点开始走的指针会和从头结点开始走的指针在入口点相交。 返回这个交点就可以了。
#include <iostream> #include <vector> #include <algorithm> #include <queue> #include <stack> using namespace std; // Definition for singly-linked list. struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode * fast = head; ListNode * slow = head; ListNode * p = NULL; //用快慢指针判断是否有环 快指针一次走两步 慢指针一次一步 有环会相遇 while(fast != NULL) { fast = (fast->next == NULL) ? NULL : fast->next->next; slow = slow->next; if(slow != NULL && slow == fast) { p = slow; //记录相遇的位置 break; } } if(p == NULL) //如果没有相遇 没有环 { return NULL; } else { ListNode * cross = head; while(cross != p) //新的结点从头开始走 另一节点从之前相遇的位置开始走 这两个结点相遇的位置就是环的入口 { cross = cross->next; p = p->next; } return cross; } } };