Sword finger offer (Second Edition) - maximum value of sliding window

Posted by samdennis on Fri, 01 Oct 2021 03:08:40 +0200

PS: Sword finger offer is not only an interview guide that many students will refer to when looking for a job, but also an algorithm Guide (the main reason why it is so popular is that it provides a step-by-step optimization solution, which I think is very friendly). Now many Internet algorithm interview questions can be found here. For the convenience of reference and review in the future, the examples in the book are implemented in Java (Second Edition). You are welcome to communicate and progress together.

GitHub: https://github.com/Uplpw/SwordOffer.

Full title link: https://blog.csdn.net/qq_41866626/article/details/120415258

1 Title Description

Given an array and the size of sliding windows, find the maximum value of all sliding windows. For example, if you enter the array {2,3,4,2,6,2,5,1} and the number 3, there are six sliding windows, and their maximum values are {4,4,6,6,5}.

leetcode link: Maximum value of sliding window (the following code has been tested and submitted)

2 test cases

Generally, functional use cases, special (edge) use cases, counterexamples and invalid test cases are considered. We can even find some rules to solve problems from test cases, and it can also make our program more complete and robust.

(1) Function use case: the array contains multiple unordered numbers.

(2) Edge use case: the number of a single element, or k=1.

(3) Invalid use case: the array is empty or k is greater than the length of the array.

3 ideas

analysis:

Here are two solutions.

Solution 1: violence solution

The most direct and intuitive way is to solve by violence. Double loops are used to solve. How many sliding windows are there in the outer loop array, and the maximum value of each window is calculated in the inner layer.

In addition, it can also be optimized. First, calculate the maximum value of the first sliding window. When calculating the maximum value of the next sliding window, judge the size relationship between the last maximum value and the last element on the leftmost side of the current sliding window:

  • If not, judge the relationship between the previous maximum value and the new element of the sliding window. If it is greater than or equal to, the maximum value of the current window is equal to the previous maximum value; otherwise, the maximum value of the current window is equal to the new element value.
  • If equal, you need to re traverse the elements of the current window to calculate the maximum value.

The time-space complexity is O ( n k ) , O ( 1 ) O(nk),O(1) O(nk),O(1)

Solution 2: using ordered queue

Whether the time complexity can be optimized again depends on how to O ( 1 ) O(1) The maximum value is found in the sliding window within the time of O(1).

Recall the previous topic, the stack containing the min function, which uses the monotone stack to obtain the "minimum value in the stack" in the O(1) time when entering and leaving the stack at will. The same is true for this problem. The difference is that "stack out operation" deletes "list tail elements", while "window sliding" deletes "list head elements".

The data structure corresponding to the window is double ended queue. This problem can be solved by using monotonic queue. When traversing the array, the monotone queue deque is guaranteed for each round:

  • Deque contains only the elements in the window ⇒ each round of window sliding removes the element nums[i - 1], and the corresponding elements in deque need to be deleted together.
  • Elements in deque are not strictly decreasing ⇒ elements nums[j + 1] are added for each round of window sliding, and all elements < nums[j + 1] in deque need to be deleted.

Monotonic queue note:
(1) The queue is placed from large to small
(2) If the first value (i.e. the maximum value) is not in the window interval, delete the first value
(3) If the added value is less than the value at the end of the queue, it will be added to the end of the queue
(4) If the new value added is greater than the value at the end of the queue, delete the value smaller than the new value added in the queue. If the new value added is added to the queue
(5) If the new value-added is greater than all the values in the queue, delete all, and then put the new value-added at the top of the queue to ensure that the queue is from large to small

The time-space complexity is O ( n ) , O ( k ) O(n),O(k) O(n),O(k)

4 code

Algorithm implementation:

import java.util.Deque;
import java.util.LinkedList;

public class MaxInSlidingWindow {
	// Solution 1: violence solution
    public static int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || nums.length == 0 || nums.length < k || k <= 0) {
            return new int[0];
        }
        if (k == 1) {
            return nums;
        }
        int length = nums.length;
        int len = length - k + 1;
        int[] array = new int[len];
        array[0] = nums[0];
        for (int j = 0; j < k; j++) {
            array[0] = (array[0] < nums[j]) ? nums[j] : array[0];
        }
        for (int i = 1; i < len; i++) {
            if (array[i - 1] != nums[i - 1]) {
                if (array[i - 1] >= nums[i + k - 1]) {
                    array[i] = array[i - 1];
                } else {
                    array[i] = nums[i + k - 1];
                }
            } else {
                int tempLength = i + k;
                array[i] = nums[i];
                for (int j = i + 1; j < tempLength; j++) {
                    array[i] = (array[i] < nums[j]) ? nums[j] : array[i];
                }
            }
        }
        return array;
    }
	
	// Solution 2: using ordered queue
    public static int[] maxSlidingWindow1(int[] nums, int k) {

        if(nums.length == 0 || k == 0) return new int[0];
        Deque<Integer> deque = new LinkedList<>();
        int[] res = new int[nums.length - k + 1];
        // No window formed
        for(int i = 0; i < k; i++) {
            // The queue is not empty. The new value added is greater than the value at the end of the queue. Delete the value in the queue that is smaller than the new value added. If you are adding the new value added to the queue
            while(!deque.isEmpty() && deque.peekLast() < nums[i])
                deque.removeLast();
            deque.addLast(nums[i]);
        }
        res[0] = deque.peekFirst();
        // After the window is formed
        for(int i = k; i < nums.length; i++) {
            // If the first value (i.e. the maximum value) is not in the window interval, delete the first value
            if(deque.peekFirst() == nums[i - k])
                deque.removeFirst();
            // The queue is not empty. The new value added is greater than the value at the end of the queue. Delete the value in the queue that is smaller than the new value added. If you are adding the new value added to the queue
            while(!deque.isEmpty() && deque.peekLast() < nums[i])
                deque.removeLast();
            deque.addLast(nums[i]);
            // The window maximum is equal to the queue header element
            res[i - k + 1] = deque.peekFirst();
        }
        return res;
    }

    public static void main(String[] args) {
        int[] arr = maxSlidingWindow(new int[]{1, 3, -1, -3, 5, 3, 6, 7}, 3);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
        System.out.println();
    }
}

reference resources
When solving the examples in this book, we refer to the solutions of some big guys, such as the official, K God and other blogs on leetcode. After the detailed explanation of each example, we will give the reference ideas or code links. Students can click in and have a look!

Reference to this example:

  1. K God solution

If there are any deficiencies or mistakes in this article, you are welcome to criticize and correct. Finally, I hope to communicate with you and make progress and get your favorite offer!!!

Topics: Algorithm Interview