A detailed summary of the common question types in the linked list of fast and slow pointers

1. Find the middle node of the linked list

insert image description here

Double pointer advanced solution

1. Define two pointers, one fast pointer and one slow pointer.
2. The fast pointer takes two steps at a time, and the slow pointer takes one step at a time.
3. When considering where the fast pointer points to, our slow pointer just reaches the middle node

Use two pointers slowand fastto traverse the linked list. slowTake one step at a time, fasttwo steps at a time. Then when fastit reaches the end of the linked list, slowit must be in the middle.

1. Define the fast and slow pointers
2. The fast pointer takes one step at a time, and the slow pointer takes two steps at a time
3. Exit the loop when the fast pointer is nullor the fast pointernext为null

insert image description here

The premise mentioned that if there are two intermediate nodes, the second intermediate node will be returned, so let's see if this solution is suitable for an even number of nodes

insert image description here
Looking at the picture, we can know that no matter whether the linked list is odd or even, it will not affect the final result.

Judgment condition:
At that timefast==null , or fast.next==nullwhen, exit the loop.
Note : Since the logical operator && judges the left side first, and then judges the right side when the left side is true, if mine is fastalready true null, then if I fast.nextwrite it on the left side, a null pointer exception will occur, so we need to judge fast first Is it null, that is, it will be fast!=nullwritten on the left

code show as below

class Solution {
    
    
    public ListNode middleNode(ListNode head) {
    
    
    //定义两个指针,一个快指针,一个慢指针
        ListNode slow = head, fast = head;
        while (fast != null && fast.next != null) {
    
    
            slow = slow.next;//慢指针一次走一步
            fast = fast.next.next;//快指针一次走两步
        }
        return slow;//返回慢指针
    }
}

Complexity analysis:

  • Time complexity O(n) , where Nis the number of nodes in the given linked list.
  • Space complexity O(1) , only need constant space to store two pointers of slow and fast.

2. Find the Kth node from the bottom

insert image description here

Problem-solving ideas:

Define a fast and slow pointer, let the fast pointer go K steps first, and then the slow pointer and the fast pointer go together. When the fast pointer is null, our slow pointer is the Kth number from the bottom.

How did the above reasoning come about?

Let's see the picture demo

insert image description here

Step 1: Let the fast pointer cur take K steps, as shown in Figure 2. Step
2: The fast pointer and the slow pointer move together, and exit the loop when the fast pointer is null
Step 3: At this time, prev is the Kth node from the bottom , just return to prev

The specific process is as follows

insert image description here

Using the fast and slow pointers as shown in the figure, first let the fast pointer go k steps first, and then let the fast and slow pointers walk one step at a time until the fast pointer points to an empty node, and the slow pointer is the kth node from the bottom

Enter the code and
pay attention to the comments! ! !

public class Solution {
    
    
    public ListNode FindKthToTail(ListNode head,int k) {
    
    
		 //判断链表是不是为空,并且k不能小于等于0	
        if (k<=0||head==null) {
    
    
            return null;
        }
        int n=0;
        ListNode prev=head;
        ListNode cur=head;
        while (n<k) {
    
    
        //判断cur是否为null
        //如果为null返回null
            if (cur==null) {
    
    
               return null;
            }
            cur=cur.next;
            n++;
            //如果将if放到下面,
            //那么判断倒数第n个结点时就会出错,n是链表长度,
            //也就是查找链表头节点时会报错
            //if (cur==null) {
    
    
            // return null;
            // }
        }
        while (cur!=null) {
    
    
            prev=prev.next;
            cur=cur.next;
        }
        return prev;
    }
 }

Author's summary:

There is an extreme condition that when the penultimate K-th node is the head node, the if cannot be placed in the position I commented in the code, as shown in the figure below
insert image description here

If you exit cur == nullat the time of , then there is a situation cur==nullthat when mine, my prev is the penultimate 5th node that meets the conditions. If you exit at this time, the result will be different from the expected result, so we will judge The condition is written above, in that case, only when our n does not meet the condition cur==null, it returns null, thus avoiding the above error

Input a linked list, output the penultimate k-th node oj in the linked list

3. Judging the circular linked list

insert image description here

Title description:

Give you a linked list, judge whether it has a ring, if it has a ring, return trueotherwise returnfalse

Fast and slow pointer solution :

Suppose classmate "A" and classmate "B" met to run together, and they came out of the dormitory building together, because "A" ran fast, so "A" arrived at the playground first to run laps, if it is not a lap (no ring), then "B" will never catch up with "A". When "B" enters the playground, because "A" is fast, it will definitely meet "B" at a certain moment, that is, run more than "B". several laps.

We can use the above ideas to solve this problem:

1. Set a fast and slow pointer
2. The fast pointer takes two steps at a time, and the slow pointer takes one step at a time.
3. When the fast pointer is empty or the next node of the fast pointer is empty, exit the loop (this means there is no ring) and return to false
4. When the slow pointer catches up with the fast pointer, it means that there is a ring and returntrue

Let's look at the picture below:

insert image description here
The code is as follows :

public class Solution {
    
    
    public boolean hasCycle(ListNode head) {
    
    
        ListNode A=head;//快指针
        ListNode B=head;//慢指针
        while(A!=null&&A.next!=null) {
    
    
            A=A.next.next;//快指针一次走两步
            B=B.next;//慢指针一次走一步
            //当两个结点相同时,意思就是相遇了
            if(A==B) {
    
    
                return true;//返回正确
            }
        }
        return false;//当出了循环说明这个链表没有环,返回错误
    }
}

Complexity Analysis
Time Complexity: O(N)O(N)O(N), where NNN is the number of nodes in the linked list.

Space complexity: O(1)O(1)O(1). We only use an additional space
complexity analysis of two pointers:

  • Time complexity O(n), where Nis the number of nodes in the given linked list.

When there is no ring in the linked list, the fast pointer will reach the end of the linked list before the slow pointer, and each node in the linked list is visited twice at most.
When there is a ring in the linked list, after each round of movement, the distance between the fast and slow pointers will decrease by one. The initial distance is the length of the ring, and because the slow pointer moves at most N times, it moves at most N rounds. (explained below)

  • Space complexity O(1), only two pointers are used for extra space

Why does the slow pointer move at most N times ? (N is the length of the linked list)

We can imagine that two people are running. Since "A" runs fast, they will definitely meet "B". The premise is mentioned above. The speed of "A" is twice that of "B". So when student "B" runs one lap, student "A" must have completed two laps (the starting point of A is calculated from the current position of student A when B enters the playground), so no matter what, they will definitely meet ,

Why does the fast pointer have to be two steps at a time, if it is three steps at a time, can it be four steps at a time ?

Example :

The answer is no! Maybe in mathematics, you can calculate the time of meeting or the number of times you move when meeting (that is because there are decimals in mathematics), but the linked list is different. Every step of it is an integer, and there is no such thing as decimals. Like flying chess when I was young, if there is a treasure box one grid away from you, then you will not get the treasure box if you take four steps, three steps, or even two steps, and you can only watch and rub it against it. Passing by, just like you are trying to create a chance to meet your goddess, she goes out at three o'clock, how about you? Go downstairs to her dormitory at 3:01, then you will never meet, this is a miss, and you can't miss a single cent. Therefore, in the process of catching up with love, we should grasp the timing and would rather come early than late. Maybe you don’t know when she will come back, but you have to be prepared, even if you come six hours early, even if it’s snowy, even if you stand Don't give up even if you are frozen into a popsicle by only wearing a thin coat for the sake of being cool on the street, all these sacrifices will be worth it when you are with her in the end! (The story comes from a certain Song teacher at station B, ahem, a bit off topic)

back to business

If you take three steps at a time:

There is an extreme situation, if your ring is an odd number, then the distance between you and him (3-1=2) is shortened by two steps each time, no matter how many even numbers are subtracted from an odd number, it is still an odd number, and you will not meet, there is just endless misses

If four steps at a time:

If the ring is an even number, then the distance between you and it is shortened by three distances each time (4-1=3). No matter how many times you subtract, he will never meet.

If you take two steps each time:

Regardless of odd or even numbers, since I take two steps each time, our direct distance is shortened by one step each time (2-1=1), all integers are multiples of 1, and we will meet eventually!

4. Find the entry of the ring list (advanced)

insert image description here

Topic: Determine whether it is a circular linked list, if the linked list has a ring, return the first node that enters the ring.

Fast and slow pointer solution :

This actually involves the knowledge of mathematics, we are still drawing examples.

insert image description here

We can think of Lit as the length when not entering the ring at this time, Xand the length of is the distance from the first node entering the ring until the fast and slow pointers intersect. Cis the remaining length in the loop.

The slow pointer moves one step at a time, and the fast pointer moves two steps at a time

So we can deduce

The length of the slow pointer: L+x
The length of the fast pointer: L+x+k(x+c)
x+c=circumference of the ring

Because there may be a situation where the ring is very short or Lvery long. If this is the case, then the fast pointer needs to walk the ring many times , so it is k(x+c).

It can be calculated by the above formula:

Since the speed of the fast pointer is twice that of the slow pointer, when the slow pointer × 2 is the distance traveled by the fast pointer

2(L+x)=L+k(x+c)+x
//The following is to remove the brackets, shift items, and merge the same type
L+x=x+c+(k-1)(x+c)
L=c+ (k-1)(x+c)
L-(k-1)(x+c)=c

We assume two nodes A and B as shown in the figure

insert image description here

No matter how many (x+c) my A pointer has moved, the position of my A pointer has not changed, but my B pointer has moved forward (k-1)(x+c) positions, so when After walking (k-1)(x+c), our B is only c nodes away from the ring entrance, and because our A pointer is also c nodes away from the ring entrance, so the position where they intersect is Entrance to the ring.

We can't judge how many of these variables are, but we can find the correct answer by looking for their direct relationship!

The picture is as follows:

Step 1: Find the intersection point

insert image description here

Step 2: Two pointers, one from the head variable and one from the intersection node

insert image description here

code show as below:

public class Solution {
    
    
    public ListNode detectCycle(ListNode head) {
    
    
        
        ListNode A=head;//慢指针
        ListNode B=head;//快指针
        //找到交点
        while(B!=null&&B.next!=null) {
    
    
				//①
            B=B.next.next;
            A=A.next;
            //切记不可以写在①那个位置
            if(A==B) {
    
    
                break;
            }
        }
        //判断因为什么退出循环
        //如果是因为结点为空,则直接返回null
        if(B==null||B.next==null) {
    
    
            return null;
        }
        //
        B=head;//B指针是头节点的位置
        //相交时,他们的交点就是环的入口结点
        while(A!=B) {
    
    
            A=A.next;
            B=B.next;
        }
        //返回A,B都行
        return A;
    }
}

Notice:

As mentioned in the comments, if()it cannot be written in the position of ①, because they are the same at the beginning. If they are written together, then it will directly exit the loop! ! !

Complexity analysis:

  • Time complexity : O(N), where N is the number of nodes in the linked list. When initially judging whether the fast and slow pointers meet, prevthe distance traveled by the pointer will not exceed the total length of the linked list; when looking for the loop-entry point, the distance traveled will not exceed the total length of the linked list. Therefore, the total execution time is O(N)+O(N)=O(N)

  • Space complexity : O(1). We only used A B2 pointers.

5. Intersecting linked list

insert image description here

Subject :

Give you two linked lists, judge whether they intersect, if intersect, return the intersection node!

Solution 1: Violent solution

Each node of the above linked list is compared with the entire linked list below. In the worst case, if the two linked lists do not intersect, the time complexity is O(n^2), so I won’t demonstrate it here. Let’s explain the time complexity A solution with degree O(n)

Solution 2: Double pointer traversal

Ideas:

We can define two pointers, start traversing from the head of the two linked lists, and then find the difference between the linked lists. After the long linked list has completed the difference, the two linked lists will traverse backwards together, exit when they are the same, and return the same result point.

Specific steps:

1. Define two pointers, traverse backwards from the head of the two linked lists respectively
2. Record the length of the two linked lists
3. Find the difference between the lengths of the linked lists
4. The long linked list finishes the difference
first Then traverse backwards at the same time until the exit is the same

As shown in the picture:

The first step: traverse the intersecting linked list

insert image description here
Step 2: The long chain list first walks through the difference, and then walks together

insert image description here

The code is as follows :

public class Solution {
    
    
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    
    
		// 一个链表为空永远不可能香蕉
        if (headA==null&&headB==null) {
    
    
            return null;
        }
        //分别记录headA headB
        ListNode A= headA;
        ListNode B=headB;
        //用来记录链表长度
        int count=0;
        //用来记录最短长度
        int sum=0;
        //用来判断哪个链表长
        boolean p=false;
        //两个链表一起走,有一个为空时,最短长度记录完成
        while (A!=null&&B!=null) {
    
    
            A=A.next;
            B=B.next;
            count++;
            sum++;
        }
        //继续走长的链表,直到长链表也走完,记录长链表的长度
        
        while (A!=null) {
    
    
            A=A.next;
            count++;
            //如果是A链表不为空,那么p为true
            p=true;
        }
        //同上
        while (B!=null) {
    
    
            B=B.next;
            //如果是B链表不为空则p不变
            count++;
        }
        //重新找到头
        A=headA;
        //同上
        B=headB;
        //让长的先走
        int n=count-sum;
        //P为真A先走n步
        if (p) {
    
    
            while (n>0) {
    
    
                A=A.next;
                n--;
            }//否则B先走
        } else {
    
    
            while (n>0) {
    
    
                B=B.next;
                n--;
            }
        }//走完链表的差值后,两个链表一起遍历
        //香蕉退出循环
        while (A!=B) {
    
    
            A=A.next;
            B=B.next;
        }
        return A;
    }
}

Complexity analysis:

  • Time complexity : O(N), a total of traversal of the completed long linked list plus a traversal of the linked list when looking for intersection points, a total of 2*n times (n represents the length of the longest linked list)

  • Space complexity : O(1),

Guess you like

Origin blog.csdn.net/xiaoyubuhuiqiche/article/details/128190645