アルゴリズム演習ポスト--49--最大スライディングウィンドウ(Java)

最大スライディングウィンドウ

1.はじめに

整数の配列numsが与えられると、サイズkのスライディングウィンドウが配列の左端から右端に移動します。スライディングウィンドウにはk個の数字しか表示されません。スライディングウィンドウは、一度に1つの位置だけ右に移動します。
スライディングウィンドウの最大値を返します。
(件名:LeetCode

示例 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
示例 2:
输入:nums = [1], k = 1
输出:[1]
示例 3:
输入:nums = [1,-1], k = 1
输出:[1,-1]
示例 4:
输入:nums = [9,11], k = 2
输出:[11]
示例 5:
输入:nums = [4,-2], k = 2
输出:[4]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length

この質問は、leecodeの簡単な質問59と同じです。

二、解決策

1.単調キュー

package com.lxf.test;

import java.util.LinkedList;

public class MaxSlidingWindow {
    
    
    public static void main(String[] args) {
    
    
        //[1,3,-1,-3,5,3,6,7]
        // 3
        maxSlidingWindow(new int[]{
    
    1,3,-1,-3,5,3,6,7},3);
    }
    public static int[] maxSlidingWindow(int[] nums, int k) {
    
    
        if(k==1||nums.length==0) return nums;
        int[] results=new int[nums.length-k+1];
        //单调队列
        LinkedList<Integer> linkedList = new LinkedList<>();
        for (int i = 0; i < nums.length; i++) {
    
    
            //保证队列头是当前窗口的最大值
            while(!linkedList.isEmpty()&&nums[linkedList.peekLast()]<nums[i]){
    
    
                linkedList.pollLast();
            }
            //将当前数组值对应下标加入队列中
            linkedList.offer(i);
            //从第一个窗口开始取数
            if(i>=k-1){
    
    
                //将当前队列头也就是当前窗口的最大值赋值到结果数组中
                results[i-k+1]=nums[linkedList.peek()];
                //预测队列头是否在下一个窗口中,不在就要移除它
                //例如:nums=[1,5,2,4,9] k=3
                //其中5在第一个窗口和第二个窗口中,在第三个窗口前就要移除
                if(linkedList.peek()<=i-k+1){
    
    
                    linkedList.pollFirst();
                }
            }
        }
        return results;
    }
}

2. Deque(公式ソリューション)

class Solution {
    
    
    public int[] maxSlidingWindow(int[] nums, int k) {
    
    
        int n = nums.length;
        Deque<Integer> deque = new LinkedList<Integer>();
        //获取第一个窗口的最大值,
        for (int i = 0; i < k; ++i) {
    
    
            while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
    
    
                deque.pollLast();
            }
            deque.offerLast(i);
        }

        int[] ans = new int[n - k + 1];
        ans[0] = nums[deque.peekFirst()];
        //从第二个窗口开始遍历(比方法1少了一层比较)
        for (int i = k; i < n; ++i) {
    
    
            while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
    
    
                deque.pollLast();
            }
            deque.offerLast(i);
            while (deque.peekFirst() <= i - k) {
    
    
                deque.pollFirst();
            }
            ans[i - k + 1] = nums[deque.peekFirst()];
        }
        return ans;
    }
}

3.ブロッキング(タイムアウト)

package com.lxf.test;

import java.util.Arrays;

public class MaxSlidingWindow {
    
    
    public static void main(String[] args) {
    
    
        //[1,3,-1,-3,5,3,6,7]
        // 3
        System.out.println(maxSlidingWindow(new int[]{
    
    1, 3, -1, -3, 5, 3, 6, 7}, 3));
    }
    public static int[] maxSlidingWindow(int[] nums, int k) {
    
    
        if(k==1||nums.length==0) return nums;
        int[] results=new int[nums.length-k+1];
        Arrays.fill(results, Integer.MIN_VALUE);
        for (int i = 0; i < nums.length; i++) {
    
    
            if(i==nums.length-k){
    
    
                break;
            }
             int j=i;
             while(j<i+k){
    
    
                 results[i]=Math.max(results[i],nums[j]);
                 j++;
             }
        }
        return results;
    }
}

4.ブロック+前処理(公式ソリューション)

class Solution {
    
    
    public int[] maxSlidingWindow(int[] nums, int k) {
    
    
        int n = nums.length;
        int[] prefixMax = new int[n];
        int[] suffixMax = new int[n];
        for (int i = 0; i < n; ++i) {
    
    
            if (i % k == 0) {
    
    
                prefixMax[i] = nums[i];
            }
            else {
    
    
                prefixMax[i] = Math.max(prefixMax[i - 1], nums[i]);
            }
        }
        for (int i = n - 1; i >= 0; --i) {
    
    
            if (i == n - 1 || (i + 1) % k == 0) {
    
    
                suffixMax[i] = nums[i];
            } else {
    
    
                suffixMax[i] = Math.max(suffixMax[i + 1], nums[i]);
            }
        }

        int[] ans = new int[n - k + 1];
        for (int i = 0; i <= n - k; ++i) {
    
    
            ans[i] = Math.max(suffixMax[i], prefixMax[i + k - 1]);
        }
        return ans;
    }
}

おすすめ

転載: blog.csdn.net/Inmaturity_7/article/details/112095256