力扣环形链表2 C++双指针题解

leetcode 环形链表

题目

题目
传送门:环形链表2

  • 样例
    样例

分析

  1. 链表问题多用双指针解决。这里考虑快慢指针。基于如下背景:
  • 初始化,slow和fast均指向链表头结点head。
  • 指针移动。slow每次移动一步,fast每次移动两步。
    这样的设置,使得fast每次相对slow多走一步,并且每一个时刻fast走的长度是slow的两倍。从相对运动的角度看,将slow看做fast的(动态)起点,则若存在环,则fast最终一定会回到这个“起点”,即一定会与slow相遇。
  1. 先考虑有环的情况。找相遇点是容易的,只需要按照如上规则移动指针并加以判断即可。
    假设相遇点已求,挖掘其中的信息
    图解
  • 首先,假设从head到环入口距离(可以理解为边数)为x,环入口到相遇点的距离为y,相遇点到环入口的距离为t。基于fast每次相对slow多走一步这个条件可列出基本的方程。

  • 分类讨论:
    – 若x > (y + t),即从head到环入口的距离大于一个环的长度,等慢指针到了入口时,快指针必定已经跑过了n圈(n >= 1),则到达相遇点时,有如下关系:

    2 ( x + y ) = x + y + n ( y + t ) 2(x+y) = x+y+n(y+t) 2(x+y)=x+y+n(y+t)
    即 x = n y − t ( n > 1 ) 即x= ny-t (n > 1) x=nyt(n>1)
    – 若x <= (y + t),即从head到环入口的距离小于或等于一个环的长度时,有如下关系:
    2 ( x + y ) = x + y + t 2(x+y) = x+y+t 2(x+y)=x+y+t
    即 x = y − t 即 x =y-t x=yt
    综上,若有环,令p1 = head, p2 = temp(相遇点),则p1与p2第1次相遇时,p1走过的路程必定为x,即为环的入口。

  1. 若无环,则通过fast指针的遍历可判断出是否无环:考虑无环的情况,若无环,则fast或fast->next最终必定为空。

代码实现

class Solution {
public:
   ListNode *detectCycle(ListNode *head) {
       /*双指针练习*/
       ListNode *slow = head, *fast = head;
       //找第一次相遇点
       while (fast && fast->next) { //判断有无环
           fast = fast->next->next;
           slow = slow->next;
           if (slow == fast) {
               break;
           }
       }
       if (fast && fast->next) { //若用 slow == fast, 则当只有一个结点的时候会判断错误
           ListNode *p1 = head;
           ListNode *p2 = slow;
           while(p1 != p2) {
               p1 = p1->next;
               p2 = p2->next;
           }
           return p1;
       }
       return NULL; //无环
   }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值