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

题目描述

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

思路解析

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

思路描述:
假设链表结构如下:
在这里插入图片描述

  • 首先判断是否是环。设置两个指针,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;
    }
}

猜你喜欢

转载自blog.csdn.net/H1517043456/article/details/107509241