Sliding window maximum value (239) problem solving difficulty: difficult

topic

You are given an array of integers numswith a ksliding window of size moving from the far left of the array to the far right of the array. kYou can only see numbers in the sliding window . The sliding window only moves to the right one bit at a time.

Returns the maximum value in a sliding window .

Example 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

Example 2:

输入:nums = [1], k = 1
输出:[1]

hint:

  • 1 <= nums.length <= 10^5
  • -10⁴ <= nums[i] <= 104⁴
  • 1 <= k <= nums.length

analyze

brute force

If this question is solved by brute force, it is relatively simple, but the time complexity is relatively high. Let me talk about the method of brute force first.

The number of numbers in the window is known k, and the number of windows can be obtained according to the original array numsand the number of numbers in the window k, that is, the length of the returned array. The formula is: nums.length - k + 1, enter the formula with Example 1: 8 - 3 + 1 = 6The number of windows in Example 1 is 6 , and the number of windows in the following cycles can be used.

insert image description here

The number of windows is known and the possibility is known, so the number of loops in the first layer directly uses the nums.length - k + 1result value as the judgment condition, and the loop in the second layer determines kthe maximum value of the values ​​in the window, and takes the maximum value of each window and writes it to the return Arrays, this is the way to brute force.

code show as below:

class Solution {
    
    
    public int[] maxSlidingWindow(int[] nums, int k) {
    
    
        int fnum = nums.length-k+1;
        int result[] = new int[fnum];
        for(int i = 0; i < fnum; i++){
    
    
            int max = -10001;
            for(int j = i;j < k+i; j++){
    
    
                if(nums[j] > max){
    
    
                    max = nums[j];
                }
            }
            result[i] = max;
        }
        return result;
    }
}

Results of the:

insert image description here

The time complexity of brute force cracking is O(n²), and the space complexity is O(1), and the solution of this method exceeds the time limit, so you have to use another method.

queue max

队列Since the topic requires obtaining the maximum value of each window, use the maximum value in the subscript of the record window cycle during the loop to ensure that the queue is in order in the queue 递减队列, so that the acquisition can be obtained 最大值directly from 队列头the acquisition. If 队列尾值 < 循环值you need to transfer the queue The tail value is popped up. If the loop subscript exceeds the number of windows, the value at the head of the queue will be popped out.

insert image description here
Steps:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]

L-R为窗口值
初始状态:L=R=0,队列:{
    
    }
i=0,nums[0]=1。队列为空,直接加入。队列:{
    
    1}
i=1,nums[1]=3。队尾值为13>1,弹出队尾值,加入3。队列:{
    
    3}
i=2,nums[2]=-1。队尾值为3-1<3,直接加入。队列:{
    
    3,-1}。此时窗口已经形成,L=0,R=2,result=[3]
i=3,nums[3]=-3。队尾值为-1-3<-1,直接加入。队列:{
    
    3,-1,-3}。队首3对应的下标为1,L=1,R=3,有效。result=[3,3]
i=4,nums[4]=5。队尾值为-35>-3,依次弹出后加入。队列:{
    
    5}。此时L=2,R=4,有效。result=[3,3,5]
i=5,nums[5]=3。队尾值为53<5,直接加入。队列:{
    
    5,3}。此时L=3,R=5,有效。result=[3,3,5,5]
i=6,nums[6]=6。队尾值为36>3,依次弹出后加入。队列:{
    
    6}。此时L=4,R=6,有效。result=[3,3,5,5,6]
i=7,nums[7]=7。队尾值为67>6,弹出队尾值后加入。队列:{
    
    7}。此时L=5,R=7,有效。result=[3,3,5,5,6,7]

code show as below:

    public int[] maxSlidingWindow(int[] nums, int k) {
    
    
        ArrayDeque<Integer> deque = new ArrayDeque<Integer>();
        int result[] = new int[nums.length-k+1];
        for (int i = 0; i < nums.length; i++) {
    
    
            // 判断值是否比尾部值大,大的话将队列的尾部值退出
            while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
    
    
                deque.pollLast();
            }
            deque.addLast(i);
            // 超出窗口的值退出队列
            if(deque.peek() <= i-k){
    
    
                deque.poll();
            }
            // 前面n-1不参与数组写入
            if(i+1 >= k){
    
    
                result[i+1-k] = nums[deque.peek()];
            }
        }
        return result;
    }

Results of the:
insert image description here

The time complexity of this method isO(n)

Guess you like

Origin blog.csdn.net/AnNanDu/article/details/126851426