写在前面: 这道题有很多解法,不乏一些心机解法,比如在内存充足情况下(正常来讲是充足的)利用链表内存顺序存取,堆的地址又是从低到高,如果链表有环,则head->next小于或者等于head。比较正常的解法应该会用到set这种数据结构,我这题是纯用数学方法。
- 定义快慢指针指向头结点,快指针速度是慢指针两倍
- 设头结点到环的起点距离为a,环的起点到两指针第一次相遇的点距离为b,两指针相遇的点再到环的起点距离为c
- 根据快指针走过路程是慢指针的两倍可得 a+2b+c=2(a+b),解得a=c
- 根据a=c可得解题思路:快慢指针第一次跑到相遇时,再跑路程a即为环起始位置
手糊了一张图帮助理解,如下
欢迎浏览我的 力扣github仓库,有JavaScript和C++两个版本,每日更新,觉得有帮助点个star呗~
C++代码:
/**
* 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,*slow=head;
while(fast && fast->next)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow){
fast=head;
while(fast)
{
if(fast==slow)
return fast;
fast=fast->next;
slow=slow->next;
}
}
}
return NULL;
}
};
JS代码:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var detectCycle = function(head) {
var fast=head,slow=head;
while(fast && fast.next){
fast=fast.next.next;
slow=slow.next;
if(fast==slow){
fast=head;
while(fast){
if(fast==slow)
return fast;
fast=fast.next;
slow=slow.next;
}
}
}
return null;
};