【力扣】环形链表II

 

🔥博客主页: 我要成为C++领域大神

🎥系列专栏【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】

❤️感谢大家点赞👍收藏⭐评论✍️

本博客致力于分享知识,欢迎大家共同学习和交流。

10f3f804036d438784915f2c6f94fb5d.gif

给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:不允许修改给定的链表

 

ec93e93faaf5d305f276b3e1896726d4.png

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

 

92e80ac002f312cd6af81a20f1b136d6.png

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

 

4c91cde2dd13138da8b4a50fb2f9d157.png

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

方法一:相交链表求交点

一、判断是否成环
①定义快慢指针,快指针每次移动两个节点,慢指针每次移动一个节点
②快慢指针相遇,说明成环,如果为空说明到头
返回相遇节点;
如果快指针到达链表尾部,说明链表无环,返回空节点。

二、求成环点
快慢指针相遇一定是在环内的,沿着相遇点切割开来,就变成了链表相交求交点的问题

相交链表求交点

ListNode *getIntersectionNode(ListNode *headA,ListNode *headB){
        if(headA == nullptr || headB ==nullptr)
        return nullptr;
        ListNode *pA=headA,*pB=headB;
        while(pA!=pB){
            pA=pA==nullptr?pB:pA->next;
            pB=pB==nullptr?pA:pB->next;
        }
        return pA;
    }

是否成环以及求相遇点

ListNode *checkCycle(ListNode *head) {
    // 定义快慢指针,快指针每次移动两个节点,慢指针每次移动一个节点
    ListNode *pFast = head;
    ListNode *pSlow = head;
    // 快慢指针相同,说明成环,如果为空说明到头
    while (pFast != nullptr && pFast->next != nullptr) {
        pFast = pFast->next->next;
        pSlow = pSlow->next;
        if (pFast == pSlow)
            return pFast; // 返回相遇节点
    }
    // 如果快指针到达链表尾部,说明链表无环
    return nullptr;
}

求成环点

ListNode *detectCycle(ListNode *head) {
        if(head == nullptr)
        return nullptr;
        ListNode *pNode=checkCycle(head);
        //如果相遇节点为空,说明到头也没相交
        if(pNode==nullptr) return nullptr;
        //否则就是相交了
        //快慢指针相遇一定是在环内的,沿着相遇点切割开来,就变成了链表相交求交点的问题
        return getIntersectionNode(head,pNode);
    }

方法二:利用快慢指针长度关系求成环点

一个快指针(每次移动两步)和一个慢指针(每次移动一步)。在环形链表中,这两个指针最终会在环内的某个点相遇。 假设从链表头到环的起点的距离为 a,环的起点到两指针相遇点的距离为 b,相遇点回到环的起点的距离为 c。 当慢指针进入环时,快指针已经在环内。为了让它们相遇,假设慢指针走了 b 的距离,快指针就走了 b+c 的距离,因为它的速度是慢指针的两倍。
所以我们有:
2(a+b) = a+b+c+b
a+b = c+b
a = c
这意味着从链表头到环的起点的距离等于从相遇点到环的起点的距离。

完整代码:

 ListNode* detectCycle(ListNode* head) {
        ListNode* pFast = head;
        ListNode* pSlow = head;
        int cycleLength = 1;
        while (pFast &&pFast->next) {
            pFast = pFast->next->next;
            pSlow = pSlow->next;
            if (pFast == pSlow) {
                ListNode* pNew = head;
                while (pNew != pSlow) {
                    pNew = pNew->next;
                    pSlow = pSlow->next;
                }
                return pSlow;
            }
        }
        return NULL;
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值