帮助你理解环形链表问题,以及找到链表入环的第一个节点


前言

环形链表问题,以及找到链表入环的第一个节点。


一、判断链表是否是环形链表

我们定义快慢指针同时指向头指针,让快指针去追慢指针,并且慢指针每次走一步,快指针每次走两步。

少说废话,上图!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

bool hasCycle(struct ListNode *head) {

    //定义快慢指针,让快指针去追慢指针
    struct ListNode *fast = head, *slow = head;

    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;

        if (slow == fast)
        {
            return true;
        }
    }
    
    return false;
}

扩展

1.slow一次走一步,fast一次走两步,一定能追上吗?请证明:

我来抽象一下图,便于理解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
所以,slow一次走一步,fast一次走两步,此时一定能追上。

2. slow一次走一步,fast一次走三步,一定能追上吗?请证明:

首先:不一定,在特殊场景下可能永远追不上。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.求出链表的入口点

第一种方法
在这里插入图片描述
在这里插入图片描述

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 *meet = slow;
            
            while (meet != head)
            {
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}

第二种方法:

在这里插入图片描述
next = meet->next;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
时间复杂度为O(m + n),空间复杂度为O(1)

struct ListNode* detectCycle(struct ListNode* head) {

    //定义快慢指针,让快指针去追慢指针
    struct ListNode* fast = head, * slow = head, * tmp = head;

    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;

        if (slow == fast)
        {
            struct ListNode *meet = slow;

            //记录meet的下一个节点
            struct ListNode *next = meet->next;
            struct ListNode *pA = head, *pB = next;

            //把meet->next置为空
            meet->next = NULL;
            
            while (pA != pB) 
            {
                pA = pA == NULL ? next : pA->next;
                pB = pB == NULL ? head : pB->next;
            }
            return pA;
        }
    }
    return NULL;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值