个人主页:@Weraphael
✍作者简介:目前学习C++和算法
✈️专栏:Leetcode + 面试/笔试
希望大家多多支持,咱一起进步!
如果文章对你有帮助的话
欢迎 评论 点赞 收藏 加关注✨
【思路】
可以使用快慢指针,然后转化成追击问题。快指针一次走2步,慢指针一次走1步,如果链表成环,快指针就一定能追上慢指针。
此篇博客详细讲述了快慢指针 —> 点我跳转
【代码实现】
bool hasCycle(struct ListNode *head)
{
struct ListNode* fast = head,*slow = head;
while (fast && fast->next)
{
//快指针一次走2步,慢指针一次走1步
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
return true;
}
return false;
}
写出以上代码并不难,关键在于证明。
slow
走1步,快指针fast
走2步,它们一定就能相遇?有没有可能会错过?请证明。【证明】
假设慢指针slow
进环时,设快指针fast
和慢指针slow
之间的距离是N
,slow
进环后,fast
就开始追加slow
,slow
每走一步,fast
就会走2步,它们之间的距离就会逐渐缩小1。
fast
和slow
之间的距离变化:
N — 起始距离
N-1
N-2
…
3
2
1
0 – 相遇
直到N的距离逐渐缩小到0,它们就一定能相遇。
【证明】
假设x = 3
,与上面同样的道理,设slow
进环时,fast
和slow
之间的距离为N
。slow
进环后,fast
就开始追击slow
,slow
走1步,fast
走3步,它们之间的距离就会逐渐缩小2。但这次的证明与上一个不同,因为上一个之间的距离逐渐缩小1,所以无论N
的值是多少,N
最后一定会被减到0。而这次证明需要对N
进行分类讨论,N
是偶数或奇数。
fast
和slow
之间的距离变化:
①当N
是偶数时,再加上fast
和slow
的距离逐渐缩小2,最后的它们之间的距离一定为0
N — 起始距离
N - 2
N - 4
…
4
2
0 – 相遇
②当N是奇数时
N
N - 2
N - 4
…
3
1
-1
当走到最后,fast
和slow
之间的距离为-1,这说明fast
在追加slow
的时候超过slow
了,此时fast
和slow
之间的距离就是周长 - 1
(往后假设周长为C),相当于进入新一轮追击。这里就要再判断C - 1
是奇数还是偶数,如果C - 1
是偶数代表一定能追的上,否则就追不上。
LeetCode链接:环形链表II
【思路】
先给出结论:一个指针从相遇点开始走,另一个指针从起始点开始走。它们最终会在入环点相遇。 后面会给出i详细的证明过程
【代码实现】
struct ListNode *detectCycle(struct ListNode *head)
{
//快慢指针找相遇点
struct ListNode* fast = head,*slow = head;
while (fast && fast->next )
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
//相遇点(slow改成fast也行)
struct ListNode* meet = slow;
//记录起始点
struct ListNode* start = head;
while (start != meet)
{
meet = meet->next;
start = start->next;
}
//最终他们会在入环点相遇
return meet;
}
}
return NULL;
}
面试官:你怎么知道一个指针从相遇点开始走,另一个指针从起始点开始走,它们最终会在入环点相遇。请证明
L
X
C
L + X
L + nC + X
2(L + X) = L + nc + X
L = nC - X
--> 意味着:一个指针从相遇点走,另一个指针从起始点走,它们最后会在入口点相遇。若证明过程有啥问题的,欢迎大佬指出,虚心接受orz