【LeetCode & 剑指offer刷题】链表题6:23 有环链表问题-链表中环的入口结点(141. Linked List Cycle)
【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)
141. Linked List Cycle
Given a linked list, determine if it has a cycle in it.
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) {}
* };
*/
/*
注意:有可能是中间的小循环
方法:利用两个runner(一个速度为1,一个为2)在list中run,
如果有循环则总会相遇(因为速度差为1),(总存在t使2t-t = kn2,n2为环的长度)
如果没有循环则fast会走到null位置,有循环时不会走到null位置
*/
class
Solution
{
public
:
bool
hasCycle
(
ListNode
*
head
)
{
if
(
head
==
nullptr
||
head
->
next
==
nullptr
)
return
false
;
ListNode
*
fast
,*
slow
;
slow
=
fast
=
head
;
while(fast && fast->next)
//
如果有环,
fast
不可能为
nullptr
,无环时,
fast
会运行到末尾
null,
退出循环
{
slow
=
slow
->
next
;
fast
=
fast
->
next
->
next
;
if
(
slow
==
fast
)
return
true
;
}
return
false
;
}
};
142
.
Linked List Cycle II
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.
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) {}
* };
*/
/*
问题:找链表中环的入口(如果不存在环则返回null)
分析:环只能在链表后部
假设有环,无环部分结点数为n1,有环部分结点数为n2, slow指针速度为 1结点/step,fast指针速度为2
假设经过t个step后相遇,则有 2t - t = n2(fast比slow多经过的结点,可以按路径长度来看), slow继续行进n1个结点就能到环入口
在设一指针entry于head, 速度也为 1结点/step, 则当entry行进n1个结点也可以到入口,entry与slow会在入口相遇
例子:
head编号0,如果设置prehead,则prehead编号为0,方便分析
↓--------------←↑
0 -> 1 ->
2
-> 3 -> 4 ->
5
slow: 0 → 1 → 2 → 3 → 4
fast: 0 → 2 → 4 → 2 → 4
无环部分路径长度2,有环部分路径长度4
相遇后,fast比slow多走了有环部分的路径长度4,故在距起点长度4的结点4处相遇
slow继续行进路径长度2就能走完整个链表即到入口,在开头设置一指针entry,则也行进路径长度2到入口与slow相遇
*/
class
Solution
{
public
:
ListNode
*
detectCycle
(
ListNode
*
head
)
{
if(head == nullptr || head->next == nullptr) return nullptr;
ListNode
*
slow
,*
fast
,
*
entry
;
slow
=
fast
=
entry
=
head
;
while(fast && fast->next)
//如果有环,fast不可能为nullptr,无环时,fast会运行到末尾null,退出循环
{
slow
=
slow
->
next
;
fast
=
fast
->
next
->
next
;
if
(
slow
==
fast
) //如果有环,找环入口
{
while
(
slow
!=
entry
)
{
slow
=
slow
->
next
;
entry
=
entry
->
next
;
}
return
slow
;
}
}
return
nullptr
;
}
};