为什么用快慢指针找链表的环,快指针和慢指针一定会相遇?

本文通过数学归纳法解析了在环形链表中,快指针与慢指针必然相遇的原因。通过分析两者间的距离变化,证明了无论初始相隔多少步,最终都将归结为快指针领先慢指针一步的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      这个问题你可以用数学归纳法来思考。首先,由于链表是个环,所以相遇的过程可以看作是快指针从后边追赶慢指针的过程。那么做如下思考:
1:快指针与慢指针之间差一步。此时继续往后走,慢指针前进一步,快指针前进两步,两者相遇。
2:快指针与慢指针之间差两步。此时唏嘘往后走,慢指针前进一步,快指针前进两步,两者之间相差一步,转化为第一种情况。
3:快指针与慢指针之间差N步。此时继续往后走,慢指针前进一步,快指针前进两步,两者之间相差(N+1-2)-> N-1步。

因此,此题得证。所以快指针必然与慢指针相遇。又因为快指针速度是慢指针的两倍,所以相遇时必然只绕了一圈。


作者:知乎用户
链接:https://www.zhihu.com/question/23208893/answer/117115415
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在C++中,快慢指针是一种非常经典的技术,可以用于检测链表是否存在,并的起始位置。 以下是通过快慢指针法解决该问题的具体步骤: ### 算法思路 1. **初始化两个指针** - 定义 `slow` `fast` 指针,初始都指向链表头节点。 2. **判断是否有** - 让 `slow` 每次移动一步,而 `fast` 每次移动两步。 - 如果存在,则这两个指针最终会在某个时刻相遇;如果没有,则 `fast` 或者 `fast->next` 最终会变为空值(即到达链表尾部)。 3. **寻的入口点** - 假设从链表头部到起点的距离为A,内距离相遇点逆时针方向回到起点的距离为B,顺时针方向则为C。当 `slow` `fast` 相遇时有公式: \[ A + B = n(A+B+C) \] (n表示圈数) - 化简得 \( A = (n-1)(A+B)+C \),这说明如果让一个新指针从头开始走,另一个指针从当前相遇点继续以单步前进,两者一定会的入口处再次相遇。 4. **算法实现** ```cpp ListNode *detectCycle(ListNode *head) { if (!head || !head->next) return nullptr; ListNode* slow = head; ListNode* fast = head; bool hasCycle = false; // 判断是否有 while(fast && fast->next){ slow = slow->next; // 指针每次前进一步 fast = fast->next->next; // 指针每次前进两步 if(slow == fast){ // 到了相交点 hasCycle = true; break; } } if(!hasCycle) // 若无直接返回null return nullptr; // 寻的入口点 slow = head; // 将slow重新定位回head while(slow != fast){ slow = slow->next; fast = fast->next; } return slow; // 返回的入口点 } ``` 5. **时间复杂度分析** 整体的时间复杂度为O(n),空间复杂度为O(1). ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值