环形链表

举报
芒果_Mango 发表于 2022/04/30 22:55:05 2022/04/30
【摘要】 大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流作者简介:CSDN C/C++领域新星创作者https://blog.csdn.net/chuxinchangcun?type=blog掘金LV3用户 https://juejin.cn/us...

大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流

作者简介:


题目要求

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


image-20220209224318672


链表带环

image-20220209224330306


方法:快慢指针

思路:

  • 定义两个指针,一个为fast 一个为slow
  • fast和slow从头开始遍历,fast每次走两步,slow每次走一步
  • 如果存在环,fast和slow一定会相遇

image-20220209224343380


  • 若无环时:

    • 奇数个结点:fast->next == NULL结束
    • 偶数个结点:fast == NULL结束

    image-20220209224412293

  • 而若有环,fast->next 和fast永远不为空


所以判断条件可以写成

while(fast && fast->next)
 //不可以写成
// while(fast->next && fast)

如果是无环的,则会通过while跳出,如果有环,不会跳出循环

fast->next不能在前面判断

image-20220209224423404


错误写法

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;
}

image-20220209224434753


正解代码

bool hasCycle(struct ListNode *head) {
    //定义快慢指针,从头开始遍历
        struct ListNode* fast = head;
        struct ListNode* slow = head;
        //其中一个条件不满足就退出while,说明走到空
        while(fast && fast->next)
        {
            //fast一次走两步,slow一次走一步
            fast = fast->next ->next;
            slow = slow->next;
            if(fast == slow)
            {
                return true;
            }
        }
        //如果是无环的,通过while跳出循环返回fasle
        return false;
}

或者写成:

class Solution {
public:
    bool hasCycle(ListNode *head) {
      if(head == nullptr )
        return false;
        ListNode* slow = head;
        ListNode* fast = head->next;
        //终止条件:slow和fast相遇->说明有环 || fast提前走到空->说明无环
        while(slow != fast)
        {
            //其中一个条件满足就退出while,说明走到空
            if(fast ==nullptr || fast->next ==nullptr)
            {
                return false;
            }
            slow = slow->next;
            fast = fast->next->next;
        }
        //说明有环
        return true; 
    }
};

问题延申1:fast一次走两步,slow一次走一步,为什么一定能相遇?会不会在环里错过,永远遇不上

fast一次走2步,slow一次走1步,fast和slow的距离不断减少1步

结论:slow一次走一步,fast一次走两步,如果存在环,slow和fast一定会在环内相遇


证明

  • image-20220209224509073

问题延申2:fast一次走n步(n>2),slow一次走一步,fast和slow能相遇吗

结论:fast一次走n步(n>2),slow一次走一步,不一定会相遇

fast一次走n步,slow一次走1步,fast和slow的距离不断减少n-1步


例如:fast一次走3步

  • image-20220209224554234
  • image-20220209224621336

例如:fast一次走4步

  • image-20220209224631571
  • image-20220209224640548

\

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。