本内容是笔者结合《代码随想录》总结所得,记录学习过程,分享知识!
1. 开篇例题:141. 环形链表
2. 题解参考
2.1 快慢指针法
class Solution {
public:
bool hasCycle(ListNode *head) {
// 特殊处理:空表和单节点表不构成环处理:直接 false
if( !head || !head->next ) return false;
// 使用快慢指针法操作
ListNode* slow = head;
ListNode* fast = head;
// 此处设置快指针跨越步数为:2
// 故需要如下循环判断条件
while(fast && fast->next){
fast = fast->next->next;
slow = slow->next;
// 相遇即返回:true
if(slow == fast) return true;
}
return false;
}
};
3. 解题思路:快慢指针与追及问题
3.1 虚设条件
注意题设条件:我们需要判断链表是否存在环!【单节点不算成环】;
成环有大有小,可能存在环外支路。(如下图)
在此设置如下定义:
- 链表入口点(如图中红色箭头点);
- 成环入口点(如图中绿色箭头点);
- 相遇点(暂未标出);
- 环外支路:即链表入口点与成环入口点之间的结点;
3.2 快慢指针相关问题【面试考点】
此处注意:快慢指针:顾名思义,需要两个指针:
- 慢指针 slow,每次只走一步;
- 快指针 fast,每次走两步;
提出问题:
- 快指针为什么每次走两步,可不可以更多步?可以。
- 为什么不一次走三步、四步或更多步数?
- 一次走两步为什么能找到相遇点?
分析推导!!!
如上图所示:A(链表入口点)、B(成环入口点)、C(相遇点)
设:
- AB 两点之间的距离为:L;
- BC 两点之间的距离为:X;
- 环形周长为:C;
显然:
- 由快慢指针的速度差可知(慢走 1、快走 2):当快指针 fast 走到 B 点时,慢指针 slow 走到 AB 两个点的中点;
- 当慢指针 slow 走到 B 点时,可能出现两种情况:
(1)由于环形较小,在慢指针 slow 走到 B 点时,快指针 fast 在环内可能走了不只一圈,此时设为:n(n >= 1);
(2)由于环形较大,在慢指针 slow 走到 B 点时,快指针 fast 在环内可能走了不到一圈;- 相遇情形:假设在点 C 处相遇,则:
- 慢指针路程:L + X;
- 快指针路程:L + X + n * C;
则两者相对路程差为:n * C;【 注意:由于指针移动速度的快慢关系,n 的取值范围:n >= 1 ,由此可知,快慢指针的走过的相对路程差最小为:一圈】;- 相遇情形(一)【成环入口点处相遇】:
(1)最优相遇情形:当 X = 0、n = 0 时,即快慢指针刚好在成环入口点 B 处相遇且快指针仅比慢指针多走一圈;
(2)一般相遇情形:当 X = 0、n != 0 时;
相遇情形(二)【环内相遇:如上图中的 C 处相遇】:
当慢指针进入环开始,即进入了一个追及问题!此时,如同快慢指针在同一跑道上,慢在前快在后,二者相对距离:C - X,由于速度差为:1,故每行动一次,相对距离就会 -1;
当 C - X - STEP * 1 = 0 (STEP 为 行动次数)时,二者相遇!- 显然有:
(1)当 X = 0、STEP = 0 时,即上述相遇情形(一)中的最优相遇情形:在入口点相遇;
(2)当 X = 0、STEP != 0 时,可得 STEP = C,即:快慢指针的最大相遇移动次数为:C,即一圈内必定追上!【面试点】;
(3)当 X != 0、STEP != 0 时,可得 STEP = C - X,即 快慢指针的移动次数与 X 成负相关!
关于提出的问题:
- 快指针为什么每次走两步,可不可以更多步?可以。
- 为什么不一次走三步、四步或更多步数?
如上分析:当慢指针进入环开始,即进入了一个追及问题!此时,如同快慢指针在同一跑道上,慢在前快在后,二者相对距离:C - X,由于速度差为:2,故每行动一次,相对距离就会 -2;
首圈内:当 C - X - STEP * 2 = 0 (STEP 为 行动次数)时,二者相遇!
上式变形:C - X = STEP * 2;
- 注意:
(1)当 C - X 为偶数时,假设为:10,则相对距离变换过程如下:
------ 10 => 8 => 6 => 4 => 2 => 0(相遇);
(2)当 C - X 为奇数时,假设为:9,则相对距离变换过程如下:
------ 9 => 7 => 5 => 3 => 1 => -1(快指针与慢指针擦肩而过,此时即首圈内未相遇!);
提问:此后是否会相遇?
非首圈内:
慢指针路程:L + X + a*C 且( a >= 1 );
快指针路程:L + X + b*C 且( b >= 1 );
若能相遇时路程差:(b - a)* C 且(a != b);
由于速度差为:2;当且仅当 (b - a)* C 为偶数时,才满足 [(b - a)* C] / 2 = STEP (为整数);
- 综上,环形相遇与快慢指针的相对速度!
- 若满足:快慢指针移动距离 / 相对速度 = 某整数 即可相遇!
- 快指针一次走两步、慢指针一次走一步,为什么能找到相遇点,何时能找到,最优情形、最差情形分别是?
- 若存在环形,自慢指针入环开始,快慢指针即构成追及问题!由于相对速度步差为:1,在有限距离内快指针一定能追上慢指针!
何时能找到:相对距离为:0 时。
最优情形:在慢指针如环点相遇,快指针最少在环内走一圈!
最差情形:移动走满一圈时。
4. 142. 环形链表 II【寻找环形入口点】
算法刷题营【Day3】:: 链表篇:追及问题【面试高频题:重在分析思路】(二):141. 环形链表;142. 环形链表 II:快慢指针在链表中的应用