Sword refers to Offer-52-the entry node of the ring in the linked list

Title description

For a linked list, if it contains a ring, please find the entry node of the ring of the linked list, otherwise, output null.

Idea analysis

This method is not our own, but the solution is indeed very clever, so this method is used as blog content.
Original method address: https://blog.nowcoder.net/n/deaa284f105e48f49f38b5d7cb809cd7?f=comment

Idea description:
Suppose the structure of the linked list is as follows:
Insert picture description here

  • First determine whether it is a ring. Set up two pointers, fasth and slwo. Fast takes two steps at a time, slow takes one step at a time. Fast will definitely enter the ring earlier than slow, and after many cycles, if it finally meets slow (assuming the encounter is at point P), it means that fast has been in a circle and there is a ring.
    In this process slow走过的距离是a+b, fast走过的距离是:a+nb+(n-1)c. (The reason for n times b and n-1 times c here is that because they finally met at point P, fast said that the distance traveled was 1 less c)
    So the speed relation is as follows: 2(a+b) = a+ nb+(n-1)c It can be seen that n = 2 due to the equality relationship. And get a = c.
  • Then the judgment of the ring entrance is carried out.
    Set slow2 to enter from pHead, and slow is now starting from the point q where it meets. Since a = c, when slow2 meets slow, it is the loop entry point.

Code

/*
 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;
    }
}

Guess you like

Origin blog.csdn.net/H1517043456/article/details/107509241