letcode:141.环形链表1

目录

做题链接:

1.什么是环形链表?

2.解题方法

3.分析

做题链接:

https://leetcode.cn/problems/linked-list-cycle/description/

1.什么是环形链表?

环形链表是一种特殊的链表数据结构,其链表最后一个结点的next指针指向链表中的某个结点,从而形成闭环。换句话说,链表里的最后一个结点的next指向链表中的某个结点,而不是通常情况下指向一个空指针(NULL)。如图所示:

由于环形链表不像普通链表一样最后一个结点的next指针指向空指针,所以我们不能像我们平时用pcur=pcur->next的方式去遍历链表,这样会造成死循环。

2.解题方法

我们需要采用快慢指针的方法来实现:

1.首先我们需要定义slow,fast指针指向头节点。

2.slow指针走一步,fast指针走两步,如果相遇(slow==fast)则返回这个位置,也就是证明此链表有环,就返回true。如果没有相遇,则继续循环这样走,直到跳出循环,返回false。

3.循环的结束条件为fast&&fast->next。

截图代码如下:

 typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {
    //快慢指针
    ListNode* slow=head;
    ListNode* fast=head;
    //slow走一步 fast走两步
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        //相遇返回true
        if(slow==fast)
        {
            return true;
        }

    }
    //则链表不成环
    return false;
}

3.分析

1.为什么跳出循环条件是fast&&fast->next,而不是fast->next&&fast?

1.当一个链表中有环时,fast和fast->next永远不会指向NULL
2.当一个链表中没有环时,fast一定会移动到链表的结尾;又因为fast一次移动两个节点,所以有两种情况:①fast移动两次后,刚好指向NULL,结束循环;②fast移动一次后就已经指向NULL,此时再进行移动,就会出现对NULL的解引用。

2.为什么slow要移动一步,fast要移动两步呢?

如图所示:slow一次走一步,fast一次走两步,fast比slow先进环。假设slow已经走到入环点,此时fast和slow之间的距离为N,接下来的追逐中,每追逐一次fast和slow之间的距离缩下一步。

也就是说:最开始的距离为N,第一次追逐后他们的距离为N-1,第二次追逐后距离为N-2,第三次为N-3,........,1,0,直到N为0为止,也就是说相遇了。

4.思考一下快指针一次走三步,四步,N步可以吗?

当fast一次走三步时:假设slow和fast的距离为N,随着追逐距离为:N-2-2-2-2....-2=0.

此时就会出现两种情况:

1.当N为偶数的时候:

N可以被减到0,快慢指针就会相遇,(在为减到0时,fast指针一直在slow指针的后面追逐slow指针)。

2.当N为奇数时:

此时随着追逐fast和slow并不会相遇N最后会等于-1,fast将slow套圈了。此时slow和fast之间的距离为C-1(C为环的长度)。就变成了slow追fast了。然后我们需要观察C-1的变化,(C-1)-2-2-2-2...-2,此时又会出现两种情况,当C-1的结果为2的倍数时,则此链表有环,如果C-1的结果不是2的倍数,则会死循环,此链表不是环形链表。

快指针⼀次⾛4、5.....步最终也会相遇,其证明⽅式同上。

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值