超详细带你手把手解决环形链表问题_

题目要求

链接:141. 环形链表 - 力扣(LeetCode) (leetcode-cn.com)


在这里插入图片描述


链表带环

在这里插入图片描述


方法:快慢指针

思路:

  • 定义两个指针,一个为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步

  • 在这里插入图片描述

  • 在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/chuxinchangcun/article/details/122379342