Fast pointer + double pointer

Fast and slow pointers in the linked list

1 Introduction to linked lists

Insert picture description here

2 Magical use of fast and slow pointers

  • The speed pointer is to define two pointers,
    • The speed of movement is fast and slow to create the desired difference
    • This difference allows us to find the corresponding node on the linked list

2.1 Find the median

  • General idea: first traverse the linked list once and record how many nodes there are,
    • Then, traverse again to find the midpoint.
  • Use fast and slow pointers
  • At the beginning, both the slow and fast pointers point to the first node of the linked list,
    • Then slow moves one pointer at a time, and fast moves two at a time

Insert picture description here

2.2 Judging the rings in the linked list

  • In the round track, the two people have a speed difference. Sooner or later they will meet. As long as they meet, it means there is a ring.
  • Two additional nodes are added to the ring. We can imagine that as long as the two pointers run into the ring, the distance between them will always be from far to near due to the speed difference. It's like the feeling that some people in our world pass by in your life.

Insert picture description here

2.3 Delete the penultimate nth node

  • First find the element before the element to be deleted, which is the n-1th node.
  • Turned into the problem of finding a node on the linked list, this is the scene where the fast and slow pointers are best at.
  • How to find the (n-1) th element?
  • At the beginning, the fast pointer is n + 1 elements faster than the slow pointer. Next, both pointers go down step by step.
  • When fast finishes, the slow pointer just stays on the (n-1) th element.
  • When n = 2 (dummyHead is the virtual head node added manually):

Insert picture description here

Double pointer

  • Two pointer techniques are divided into two categories,
    • Speed ​​pointer,
    • Left and right hands.
  • The former solves mainly the problems in the linked list,
    • Such as determining whether the linked list contains a ring;
    • The latter mainly solves problems in arrays (or strings),
    • For example, binary search.

First, the common algorithm of fast and slow pointers

Knowing that the linked list contains a ring

ListNode detectCycle(ListNode head) {
    ListNode fast, slow;
    fast = slow = head;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow)
            break;
    }
    
    slow = head;
    while (slow != fast) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}
  • When meeting for the first time, slow walks k steps, then the fast pointer walks 2k
    • fast takes k steps more than slow
    • k is the length of the ring
    • Because their speed difference is only 1! ! !
  • Let the distance between the meeting point and the starting point of the ring be m,
    • The distance between the starting point of the ring and the head node is k-m,
    • In other words, if you advance k-m steps from the head, you can reach the beginning of the ring.
    • If you continue to advance k-m from the point of encounter, it also happens to reach the beginning of the ring.
  • As long as we repoint any of the fast and slow pointers to the head, and then the two pointers advance at the same speed, they will meet after k-m steps. The meeting point is the starting point of the ring.

Insert picture description here

Find the midpoint of a linked list

ListNode slow, fast;
slow = fast = head;
while (fast != null && fast.next != null) {
    fast = fast.next.next;
    slow = slow.next;
}
// slow 就在中间位置
return slow;

  • When the length is odd, slow happens to stop at the midpoint;
  • Even, the final position of slow is to the right of the middle:

  • An important function of finding the midpoint of a linked list is to merge and sort the linked list.

Recall the merge sort of the array: find the midpoint index to recursively divide the array into two, and finally merge the two ordered arrays. For linked lists, merging two ordered linked lists is very simple, the difficulty lies in dichotomy.

But now that you have learned to find the midpoint of the linked list, you can achieve a dichotomy of the linked list. This article will not expand on the specific content of merge sort.

Find the penultimate element of the linked list

  • Let the fast hand go k steps first, then the fast and slow hands start to advance at the same speed.
  • In this way, when the fast pointer reaches null at the end of the linked list, the position of the slow pointer is the penultimate kth linked list node (for simplicity, it is assumed that k will not exceed the length of the linked list):

ListNode slow, fast;
slow = fast = head;
while (k-- > 0)
fast = fast.next;

while (fast != null) {
slow = slow.next;
fast = fast.next;
}
return slow;

Second, the commonly used algorithm of the left and right pointers

  • The left and right pointers actually refer to two index values ​​in the array,
  • Generally initialize left = 0, right = nums.length-1.

1. Binary search

The previous binary search algorithm is explained in detail. Here I will only write the simplest binary search algorithm, which aims to highlight its dual pointer characteristics:

int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while(left <= right) {
int mid = (right + left) / 2;
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid - 1;
}
}

2. The sum of two numbers

Let's take a look directly at the LeetCode title:

As long as the array is ordered, you should think of the double pointer technique. The solution to this problem is somewhat similar to binary search. The size of sum can be adjusted by adjusting left and right:

3. Reverse the array

void reverse(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
// swap(nums[left], nums[right])
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right–;
}
}

4. Sliding window algorithm

This may be the highest level of the double pointer technique. If you master this algorithm, you can solve a large class of substring matching problems, but the "sliding window" algorithm is slightly more complicated than the above algorithms.

Fortunately, this type of algorithm has a frame template. The next article is going to explain the "sliding window" algorithm template to help you kill several LeetCode substring matching problems.

link

  • https://www.cnblogs.com/kyoner/p/11087755.html
Published 589 original articles · 300 praises · 80,000 + views

Guess you like

Origin blog.csdn.net/zhoutianzi12/article/details/105495515