代码随想录算法训练营第四天(补充)|142.环形链表
142.环形链表II(补day04)
题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/
双指针法
这道题其实有两小问,第一个是判断链表中是否有环,第二个是找出环的起始结点。这道题方法比较多,这里展示了快慢指针法来解决环的问题,具体代码如下:
ListNode *detectCycle(ListNode *head) {
ListNode*fast=head;
ListNode*slow=head;
while(fast!=NULL&&fast->next!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
{
slow=head;
while(slow!=fast)
{
slow=slow->next;
fast=fast->next;
}
return fast;
}
}
return NULL;
}
其实主要是两个疑难点:
- fast指针与slow指针相遇与有环成等价关系吗?fast指针可不可能直接跳过slow指针呢?
答:由于slow一次性走一步,fast一次性走两步,以slow为参考系,fast只走一步。由于在相遇前,肯定是fast在追赶slow(fast要比slow多走几圈),当假设slow静止的时候,fast是一步一步追赶的,所以fast不可能跳过slow,两者必然能相遇。相遇了说明fast回来了,那么肯定是有环的。
- 明白1之后,如何找到环的起始位置呢?
答:我们设该链表长度为x+y+z,其中,x为环外,(y+z)为环内且y为前半圈,z为后半圈。当fast指针和slow指针相遇时,一定满足:
2
(
x
+
y
)
=
x
+
y
+
n
(
y
+
z
)
2(x+y)=x+y+n(y+z)
2(x+y)=x+y+n(y+z)
即:
x
=
n
(
y
+
z
)
−
y
=
(
n
−
1
)
(
y
+
z
)
+
z
x=n(y+z)-y=(n-1)(y+z)+z
x=n(y+z)−y=(n−1)(y+z)+z
由于n>=1,我们取n=1,可得:x = z
由此说明:从链表的起始位置到环的起始位置,与相遇点到环的起始位置相等!由此关系可确定环的起始位置了。
具体的代码细节:(有些时候代码细节可能比思路更重要!)
-
while(fast!=NULL&&fast->next!=NULL),循环条件要注意,由于fast一次性走两步即fast=fast->next->next,所以要求fast和fast->next都决不能是空指针,否则会引起空指针异常!
-
slow=head;将slow”归零“,尽量不要定义太多指针,能用之前的就用之前的
-
用代码语言表示满足x = z关系的环的起始节点:
slow=head;
while(slow!=fast)
{
slow=slow->next;
fast=fast->next;
}
return fast;