原题:
Given a linked list, return the node where the cycle begins. If there is no cycle, returnnull
.
=>找到单向链表的环的起点,若没有环,返回null
Follow up:
Can you solve it without using extra space?
=>能否不使用额外的空间。
/**
* 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) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
}
};
晓东分析:
看单向链表中是否存在环,晓东之前已经讲过了。这篇文章主要讲一下,如何找到这个环的起点,其实方法很简单,就是在快慢指针相交的时候,把快指针移到开始,然后大家都以1步的步长开始运动,再次遇到的时候就是环的起点。如何来证明这个做法呢,晓东来简单讲解一下。假设如下图:
我们假设快慢指针相会于C点。这个时候他们走过的路程:
快指针路程=慢指针路程+N*圆的周长=AB的距离+BC距离+M*圆的周长(M和N都是整数,不一定相等)
而我们知道快指针的路程,其实是慢指针路程的两倍。
也就是说:
快指针路程=2*慢指针的路程
所以2*慢指针的路程=慢指针路程+N*圆的周长
所以,慢指针路程=N*圆的周长。
代入上式得到:
2*N圆的周长=AB的距离+BC距离+M*圆的周长
所以AB的距离+BC距离=L*圆的周长
所以AB的距离= L*圆的周长-BC距离。
因此,我们从C点开始的慢指针,和从A点开始的慢指针肯定会相遇于B点。
代码实现:
/**
* 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) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(head == NULL || head->next == NULL) return NULL;
ListNode *fast = head->next->next;
ListNode *slow = head->next;
while(fast != slow && fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
if(fast == NULL || fast->next == NULL)
return NULL;
fast = head;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
};
运行结果:
16 / 16test cases passed.
| Status:
Accepted |
Runtime: 68 ms
|
希望大家有更好的算法能够提出来,不甚感谢。
若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·