如何理解使用动态规划求解滑动窗口最大值
1. 题目描述
给定一个数组nums
,有一个大小为k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k
个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
示例:
输入: 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. 题解
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
if (n * k == 0) return new int[0];
if (k == 1) return nums;
int [] left = new int[n];
left[0] = nums[0];
int [] right = new int[n];
right[n - 1] = nums[n - 1];
for (int i = 1; i < n; i++) {
// from left to right
if (i % k == 0) left[i] = nums[i]; // block_start
else left[i] = Math.max(left[i - 1], nums[i]);
// from right to left
int j = n - i - 1;
if ((j + 1) % k == 0) right[j] = nums[j]; // block_end
else right[j] = Math.max(right[j + 1], nums[j]);
}
int [] output = new int[n - k + 1];
for (int i = 0; i < n - k + 1; i++)
output[i] = Math.max(left[i + k - 1], right[i]);
return output;
}
看了LeetCode的官方题解,一开始没有搞明白,就到评论区看看。。。
评论区说,分块处理数组,当滑动窗口跨越两个块,这个滑动窗口最大值就是左块的最大值和右块的最大值中较大的那个。
提问:
当滑动窗口包含3,-1,-3
时,这个滑动窗口就跨越了两个块,右块的最大值只能是-3
,因为这时右块只有一个值-3
。而左块有两个值,怎么知道左块的最大值是3
呢?我的意思是怎么只比较3
和-3
,从图中的确很直观地看到3
是左块中最大的值,如果把-1
换成是4
呢?
当看到right
数组前三个数为4,4,4
时,就会发现left
数组和right
数组的规律。
left
数组的每个块里面的右边的数总是大于等于左边的数,而right
数组的每个块里面的左边的数总是大于等于右边的数。left
数组和right
数组的规律是一样的,只是方向不同。
解答:
当滑动窗口包含3,-1,-3
时,right
数组包含3,-1,5
,因为3>=-1
,所以只需要比较3
和-3
。
参考: