链表经典题目:判断链表中是否存在环(一)

这是力扣上的一道题,题目是这样的:
在这里插入图片描述
存在环的链表和正常的链表不同在于存在环的链表不能遍历,因为没有尾部的存在。

在开始做题的时候,博主想到的方法是每经过一个节点,就将这个节点断开,判断下一个节点所指向的节点是不是指向NULL,如果存在环的话,开始成环的节点就会指向NULL。如下图所示:
在这里插入图片描述
但是博主忽略了一点,就是如果链表中没有环的话,尾部也会存在NULL,这样子在倒数第二个节点也会出现上图的情况。
在这里插入图片描述
如上图,在节点0的位置,0所指向的节点也指向NULL,但是链表中并没有环。这就陷入了死胡同,说明这种解法是存在问题的。

之后我就想到了链表中比较常用的双指针法,也叫快慢指针。

快慢指针解题

将带环链表画的更形象一点,如下图:
在这里插入图片描述
在起始位置有两个指针,快指针一次走两步,慢指针一次走一步,也就是说,快指针的速度是慢指针的2倍。当快指针走到环的入口A点时,慢指针只走了前面路程的一半。
在这里插入图片描述
当慢指针走到环的入口时,由于不知道环的长度,快指针已经绕着环走了N圈(N>=0),但是快指针和慢指针之间必然相差距离X。
在这里插入图片描述

慢指针走一步,快指针走两步,相差距离变为X-1
慢指针走两步,快指针走四步,相差距离变为X-2
慢指针走三步,快指针走六步,相差距离变为X-3

以此类推,快指针一定会和慢指针相遇。
这就是用快慢指针的方法判断环状链表。代码如下:

bool hasCycle(struct ListNode *head) {
    //可以用快慢指针来解决
    if(head == NULL)
        return false;
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    //因为fast指针一次走两步,也要保证fast->next不为空
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(fast == slow)
            return true;
    }
    return false;
}

这里再解释一下为什么fast不能一次眺三步、四步…n步:
如果fast一次眺三步,快指针和慢指针的距离每次就会变为X-2、X-4、X-6…,这样如果快慢指针之间的距离是奇数就有可能错过,而且不可能再追上。
fast眺四步,之间的距离变化就是3的倍数
以此类推,所以眺两步最合适。

可以把两步的快慢指针看作一对男女,如果始终保持这样,无论多元的距离,都一定会再相遇。但是如果在前面的人走快哪怕一步,可能今生都会错过。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值