欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

剑指Offer-52——链表中环的入口节点

程序员文章站 2022-03-14 21:00:33
...

题目描述

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

思路解析

这个方法不是自己的,但是确实解法很巧妙因此就以此方法作为博客内容了。
原方法地址:https://blog.nowcoder.net/n/deaa284f105e48f49f38b5d7cb809cd7?f=comment

思路描述:
假设链表结构如下:
剑指Offer-52——链表中环的入口节点

  • 首先判断是否是环。设置两个指针,fasth和slwo。fast一次走两步,slow一次走一步。fast肯定会比slow更早的进入环中,且经过多次循环,最终如果和slow相遇了(假设相遇在P点),说明fast一直在转圈,存在环。
    在这个过程中slow走过的距离是a+b,fast走过的距离是:a+nb+(n-1)c。(这里的n倍b和n-1倍c的原因是,由于最后在P点相遇了,因此fast说走的路程少1个c)
    因此速度关系式如下:2(a+b) = a+nb+(n-1)c 可知,由于要满足等式关系,n = 2。而得到a = c。
  • 然后在进行环入口的判断。
    设置slow2从pHead开始进入,而slow此时正从相遇的q点出发。由于a = c,当slow2于slow相遇的地方,就是环入口点。

代码

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if(pHead == null || pHead.next ==null) return null;
        ListNode fast = pHead;
        ListNode slow = pHead;
        while(fast!=null||fast.next!=null){
            //由于如果存在环,就会一直循环下去,如果不存在环,就会在满足要求后跳出循环,返回一个null
            fast = fast.next.next;//快指针一次走两步
            slow = slow.next;//慢指针一次走一步
            if(fast==slow){
                //当快慢指针相遇
                ListNode slow2 = pHead;
                while(slow2!=slow){
                    slow2 = slow2.next;//slow2指针从phead出进入一次走一步当与slow相遇即为环入口
                    slow = slow.next;
                }
                return slow2;
            }
        }
        return null;
    }
}