环形链表

给定一个链表的头节点head,返回链表开始入环的第一个节点。如果链表无环,则返回null

如果链表中有某个节点,可以通过连续跟踪next指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数pos来表示链表尾连接到链表中的位置**(索引从0开始)**。如果pos-1,则在该链表中没有环。注意:pos不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改链表。

提示:

  • 链表中节点的数目范围在范围[0, 10^4]
  • 10^5 <= Node.val <= 10^5
  • pos的值为-1或者链表中的一个有效索引

进阶:你是否可以使用O(1)空间解决此题?

142.环形链表

直接进阶吧,搞哈希表太没水准了

这里主要是一个数学问题,我们弄两个快慢指针遍历链表:快指针每次前进两个节点,慢指针每次前进一个节点。

如果链表无环,那么快指针到达空指针处,返回结果。

如果链表有环,那么快慢指针会在环内相遇。设环外节点数为a,环内节点数为b,快慢指针相遇时快指针前进了f个节点,慢指针前进了s个节点。

首先快指针速度是慢指针的两倍:f = 2s

其次快指针比慢指针多走的节点数为环内节点的整数倍:f = s + nb

联立上面两个有:s = nb

也就是此时慢指针走过的节点数为环内节点数的整数倍。也就是再走a个节点能够到达环的起点数。

为了获得a,让快指针打道回府回到起点处,快慢指针同时前进,每次都移动一个节点。当二者相遇时,即是在环的开始处。

说完啦!上代码!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 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;
while(true){
if(fast == nullptr || fast->next == nullptr){
return nullptr;
}
slow = slow->next;
fast = fast->next->next;
if(fast == nullptr){
return nullptr;
}
if(slow == fast){
break;
}
}
fast = head;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return slow;

}
};
Contents
|