单向环形链表

环形链表的定义

文字解释

单向链表中的特殊的数据结构,不存在尾节点,也无法进行遍历操作,会陷入死循环。

图解

如下图中所示,相当于在我们平常理解的正常的单向链表的尾节点又继续指向链表中的某个节点,这个指向的节点可以是头节点中间节点,也可以中它本身
在这里插入图片描述

在这里插入图片描述

环形链表相关问题

1、如何判断是否为环形链表

判断方法

通过快慢指针的方式解决问题(fast and slow)

slow 走一步,fast 走两步
(至于fast为啥要走2步,下文中有解释)

如果链表中存在环形结构,则 fast 会再次遇见 slow

具体代码如下:

bool hasCycle(struct ListNode *head) 
{
    struct ListNode *slow = head,*fast = head;
    while(fast&&fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;//快慢指针操作
        
        if(slow == fast)
        {
            return true;//相遇则返回真
        }
    }
    return NULL}

但这里存在两个问题就是:

  • 这样走fast一定能遇上 slow 吗,是否会错过 slow
  • fast 走 N(N>2) 是否能有同样的效果

方法解释

问题1
  • 这样走 fast 一定能遇上 slow 吗,是否会错过 slow
    结论:一定为相遇。

证明:

第一步:
slow 和 fast,fast 一定是先进环,这时 slow 走了入环前一半的距离
在这里插入图片描述

第二步:
随着 slow 进环 fast 已经在环里面走了一段,走多少与环的大小有关,假设 slow 进环时,slow 和 fast 的距离为N

在这里插入图片描述

第三步:
slow 进环,fast 开始追 slow ,且他们之间开始的距离为 N , 因为每循环走一次,slow 与 fast 之间的距离就为 N-1,在经过几次循环后 N 就减为0,则 slow 与 fast 一定会相遇。

问题2
  • fast走N(N>2)是否能有同样的效果
    结论:不一定

证明:

假设 slow 一次走1步,fast 一次走 3 步
slow进环后(因为fast较快可能以及走过一圈或多圈但不影响),fast 和 slow 之间的距离为 N , fast 开始追 slow

则他们之间的距离变化:
N 为偶数时: N——> N - 2 ——> N - 4 ——>……2——>0(可以追上)
N 为奇数时: N——> N - 2 ——> N - 4 ——>……1——>-1(这一次追不上)

如果N为奇数,距离变为-1意味着他们之间的距离变为 C-1 (C为环的周长)
如果 C-1 为奇数,则永远追不上(会陷入死循环)
如果 C-1 为偶数,则可以追上

同理可知N为其他数时能追上的可能性不一定,当N为2时为最好的解决办法。

2、如何确定环形链表入口位置

入口位置即下图中 2 这个结点相对于头节点的位置。

在这里插入图片描述

基于上文的证明,先给出以下结论:一个指针从相遇点开始走,一个指针从链表头开始走,他们会在环的入口点相遇。

在这里插入图片描述
追上相遇过程中:
慢指针走的距离:L + X
快指针走的距离:L + N * C + X (N>=1)
(N为他们相遇前,fast 在环里面走的圈数)

快指针走的路程为慢指针的2倍
2 * ( L+X )= L + N*C + X

L + X = N * C

L = N *C - X

L = ( N-1 ) * C + (C - X)
标记的位置为从 meetNode 又走到 meetNode
结合上图可证明结论成立

代码:

struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode *fast = head, *slow = head;
    while(fast&&fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
        {
            //相遇
            struct ListNode *meetNode = slow;
            while(meetNode != head)
            {
                meetNode = meetNode->next;
                head = head->next;
            }
            return meetNode;

        }
    }
    return NULL;
}

相关题目链接

LeetCode:
环形链表I
环形链表II

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星河&'

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值