题目要求
链表带环
方法:快慢指针
思路:
- 定义两个指针,一个为fast 一个为slow
- fast和slow从头开始遍历,fast每次走两步,slow每次走一步
- 如果存在环,fast和slow一定会相遇
- 若无环时:
- 奇数个结点:fast->next == NULL结束
- 偶数个结点:fast == NULL结束
- 而若有环,fast->next 和fast永远不为空
所以判断条件可以写成
while(fast && fast->next)
//不可以写成
// while(fast->next && fast)
如果是无环的,则会通过while跳出,如果有环,不会跳出循环
fast->next不能在前面判断
错误写法
bool hasCycle(struct ListNode *head) {
struct ListNode* fast = head;
struct ListNode* slow = head;
//此处要fast放前面,不然当fast为NULL进行判断时,fast->next 是对空指针解引用,有问题
while(fast->next && fast)
{
fast = fast->next ->next;
slow = slow->next;
if(fast == slow)
{
return true;
}
}
return false;
}
正解代码
bool hasCycle(struct ListNode *head) {
//定义快慢指针,从头开始遍历
struct ListNode* fast = head;
struct ListNode* slow = head;
while(fast && fast->next)
{
//fast一次走两步,slow一次走一步
fast = fast->next ->next;
slow = slow->next;
if(fast == slow)
{
return true;
}
}
//如果是无环的,通过while跳出循环返回fasle
return false;
}
问题延申1:fast一次走两步,slow一次走一步,为什么一定能相遇?会不会在环里错过,永远遇不上
fast一次走2步,slow一次走1步,fast和slow的距离不断减少1步
结论:slow一次走一步,fast一次走两步,如果存在环,slow和fast一定会在环内相遇
证明
*
问题延申2:fast一次走n步(n>2),slow一次走一步,fast和slow能相遇吗
结论:fast一次走n步(n>2),slow一次走一步,不一定会相遇
fast一次走n步,slow一次走1步,fast和slow的距离不断减少n-1步
例如:fast一次走3步
例如:fast一次走4步