Determine whether there is a ring in the linked list and find the ring entry (illustration)

Algorithm to determine whether there is a ring in the linked list and find the ring entry

@author:Jingdai
@date:2020.12.26

Title description

Determine whether there is a ring in the given linked list, if there is a ring, find the entry of the ring and output it, if there is no ring, output it null.

Idea and code

First of all, the first question is how to judge whether there is a ring in a linked list? Children's boots familiar with fast and slow pointers must know that judging whether there is a ring in the linked list is a typical problem that can be solved with fast and slow pointers.

We use two pointers, one slow pointer slowPointerand one fast pointer fastPointer. They all start from the beginning, the slow pointer walks one step at a time, and the fast pointer walks two steps at a time. If there is a ring, the fast and slow pointers will definitely meet. Based on this, it is judged whether there is a ring.

The next question is how to find the entrance of the ring. This problem is a little more complicated, look at the picture below.

Insert picture description here

The outer length of the ring is l, and the red point is the meeting point. When meeting, the slow pointer is gone l + a, the fast pointer is gone l + n (a + b) + a, it nis the number of turns, and the distance of the fast pointer is twice that of the slow pointer, which can be obtained by simplification l = (n - 1) (a + b) + b. Ring circumference is provided ccan be obtained l = (n - 1) c + b, i.e. la distance within the ring and the rotation n-1ring walk bthe same distance. If you walk such a long distance from the meeting point at this time, you will just reach the ring entrance. We can then set a pointer to start from scratch, start another pointer away from the meeting point, when they meet, that are gone l, they will meet in the ring entry point, according to this you can find a ring entrance.

Note: Careful people may wonder why slow pointer in the ring just take a awhile will not go in a circle add ait? Because the slow pointer will only meet the fast pointer in one circle. When the slow pointer enters the ring, the distance between the fast and slow pointers must be less than the perimeter of the ring. Here we take a limit, assuming that the distance between the fast and slow pointers is equal to the perimeter of the ring (not actually available). Then the fast and slow pointers are at the entrance of the ring. When the slow pointer goes one circle and the fast pointer goes two circles, they will meet again at the entrance of the ring, that is, when the distance is the maximum, the slow pointer will only go one circle, and the distance is the largest The value is not available, so the slow pointer will not go to one circle, so the slow pointer will definitely meet the fast pointer within one circle.

The final code is as follows.

public ListNode detectCycle(ListNode head) {
    
    

    if (head == null || head.next == null) {
    
    
        return null;
    }

    ListNode dummy = new ListNode();
    dummy.next = head;

    ListNode fastPointer = head.next;
    ListNode slowPointer = head;
    while (fastPointer != null && fastPointer.next != null) {
    
    
        slowPointer = slowPointer.next;
        fastPointer = fastPointer.next.next;
        if (fastPointer == slowPointer) {
    
     // hasCicle
            slowPointer = dummy;
            while (slowPointer != fastPointer) {
    
    
                slowPointer = slowPointer.next;
                fastPointer = fastPointer.next;
            }
            return slowPointer;
        }
    }
    return null;
}

Guess you like

Origin blog.csdn.net/qq_41512783/article/details/111754088