带环链表问题详解

一.什么是环形链表

环形链表是一种链表的尾结点指向头结点或者其他结点的特殊结构。这个就是环形链表的一种:

二.环形链表的判定

2.1具体题目的举例

2.2解题思路

通过快慢指针来判定,一个指针为慢指针一次走一个,一个指针为快指针一次走两个,如果该链表为环形链表,快指针先进入环形,慢指针后进入,该题变为追击问题,则两指针一定会相遇。慢指针刚进入时,两指针的距离,最好的情况是刚好相遇;最坏的情况为相距一个环。我们只用判断两指针是否会相遇如果链表无环,fast会先走到空

 2.3思路的解释

slow一次走一个,fast指针一次走两个为什么能追上?fast一次走3,4,5~n呢?

为什么会相遇有没有可能一直错过?

2.3.1slow一次走一个,fast指针一次走两个为什么能追上?

假设slow刚进入环时两指针间的距离为N,fast一次走两位,slow一次走一位,则两者的的相对运动距离为1。则fast到slow的距离变化如下:

N--N-1---N---2----N-3-----------0    每追击一次距离减少一个,为0时追上了。

 2.3.4fast一次走3,4,5~n呢?

假设slow刚进入环时两指针间的距离为N,fast一次走三位,slow一次走一位,则两者的的相对运动距离为2。则fast到slow的距离变化分为两类(N为奇数和偶数的情况)如下:

1.N为奇数时:N→N-2→N-4→……1→错过了进行新一轮的追击:设这个环形的长度为C,这时两指针的距离为C-1,这时C要分为奇数偶数,分类讨论:

 ①C为奇数,则C-1为偶数:

   C-1→C-3→C-5→……0追到了

 ②C为偶数,则C-1为奇数:

 C-1→C-3→C-5→……1→错过了进行新一轮的追击,同样是该情况。

2.N为偶数时:N→N-2→N-4→……0 追到了

总结:

1.N为偶数时,第一轮就追到了

2.N为奇数时,第一轮追击会错过,两者距离变为C-1

a.C-1为偶数时,第二轮就追击上了。

b.C-1为奇数时,永远追不上。

由上面推理可知fast一次走3,4,5~n情况类似。

同时存在N是奇数C为偶数时永远追不上。

 

2.3.5 判断相遇是否会一直错过?

假设slow刚进入环时两指针间的距离为N,fast一次走三位,slow一次走一位,则两者的的相对运动距离为2。设从开始到入环的距离为L,当slow刚如环时,slow运动了L,fast运动了

L+X*C+C-N        X为fast绕了几圈环。

且fast的移动位移为slow的3倍,可得:

fast=3*slow

L+X*C+C-N=3L

2L=(X+1)*C-N  由这个式子通过数学分析得:2L是偶数

偶数=(X+1)*C-N  如果要让(X+1)*C-N为偶数则:

①N为偶数时,C为偶数

②N为奇数时,C为奇数

由上个分析可知N是奇数C为偶数时永远追不上

我们已经分析了两种情况,N是奇数C为偶数的情况不可能出现,所以一定会相遇。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    struct ListNode *slow=head;
    struct ListNode *fast=head;
    while(fast&&fast->next)
    {
      slow=slow->next;
      fast=fast->next->next;
      if(fast==slow)
      {
        return true;
      }
    }
    return false;
}

 

 三.寻找环的入口

3.1具体题目的举例

3.2解题思路

将头节点记为head,head指针一次移动一位,另fast指针一次走2位,slow指针一次走一位,找到fast和slow指针相遇的地点记为meet,meet指针一次移动一位,meet和head同时移动相遇时即为环的入口。

3.3思路的解释 

假设slow刚进入环时两指针间的距离为N,fast一次走二,slow一次走一位,则两者的的相对运动距离为1。设环的长度为C,设从开始到入环的距离为L,设slow与fast相遇时在环中移动了N,当两者相遇时

slow移动了:L+N

fast移动了:L+X*C+N        X为fast绕了几圈环。

fast=2*slow

L+X*C+N  =2*(L+N)

L=(X-1)*C+C-N(X>=1)

由此公式可知C-N=L,C-N又是meet到环入口的距离,所以meet和head的相遇点为环的入口。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *slow=head;
    struct ListNode *fast=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;
}

  • 42
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值