算法:Sliding Window Maximum(滑动窗口最大值)

说明

算法:Sliding Window Maximum
LeetCode地址:https://leetcode.com/problems/sliding-window-maximum/

题目:
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window.

Example:

Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3
Output: [3,3,5,5,6,7] 
Explanation: 

Window position                Max
---------------               -----
[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

Note:
You may assume k is always valid, 1 ≤ k ≤ input array’s size for non-empty array.

Follow up:
Could you solve it in linear time?

解题思路1

把数组按照个数为k分组,最后一组可能不是全部数据。以组为单位,从左到右方向,逐个计算组内遇到的最大数,记录为新的数组leftMaxArray;再从右到左方向,逐个计算组内遇到的最大数,记录为新的数组rightMaxArray.
因为从左到右方向–>是最大数,从右到左方向<–也是最大数,所以在某个位置index, k个数里面最多只能跨两个域,所以Max(leftMaxArray[index], rightMaxArray[index - k + 1])就是最大数。

可能文字不清晰,直接拿例子数据说明:

Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3

划分数组分块, size k=3. 最有一块个数可能小于k.
1,3,-1 | -3,5,3  | 6,7 |

--> 从左到右方向, 计算分块里遇到的最大数. 
leftMaxArray[] = 1,3,3 | -3,5,5  | 6,7 

<-- 类似的从右到左计算分块里遇到的最大数.
rightMaxArray[] = 3,3,-1 | 5,5,3  | 7,7 

现在, 滑动窗口在位置i, sliding-max(i) = max{rightMaxArray(i), leftMaxArray(i+w-1)}
sliding_max = 3, 3, 5, 5, 6, 7

代码实现1

public class SlidingWindowMaximum {

    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k <= 0) {
            return new int[0];
        }
        int len = nums.length;
        int[] windowMaxArray = new int[len - k + 1];
        int[] leftMaxArray = new int[len];
        int[] rightMaxArray = new int[len];

        int rightIndex;
        for (int i = 0; i < len; i++) {
            leftMaxArray[i] = i % k == 0 ? nums[i] : Math.max(leftMaxArray[i - 1], nums[i]);
            rightIndex = len - i - 1;
            rightMaxArray[rightIndex] = (i == 0 || (rightIndex + 1) % k == 0) ? nums[rightIndex] : Math.max(rightMaxArray[rightIndex + 1], nums[rightIndex]);
        }

        for (int j = 0; j <= len - k; j++) {
            windowMaxArray[j] = Math.max(leftMaxArray[j + k - 1], rightMaxArray[j]);
        }

        return windowMaxArray;
    }

    public static void main(String[] args) {
        int[] nums = {1,3,-1,-3,5,3,6,7};
        int k = 3;
        SlidingWindowMaximum obj = new SlidingWindowMaximum();
        int[] windowMax = obj.maxSlidingWindow(nums, k);
        System.out.println("Output: " + Arrays.toString(windowMax));
    }



}

运行结果

Output: [3, 3, 5, 5, 6, 7]

代码执行效率

Runtime: 4 ms, faster than 94.07% of Java online submissions for Sliding Window Maximum.
Memory Usage: 39.6 MB, less than 87.97% of Java online submissions for Sliding Window Maximum.

总结

两个方向思维,分块处理。

代码下载:

猜你喜欢

转载自blog.csdn.net/zgpeace/article/details/88372784