如何理解使用动态规划求解滑动窗口最大值

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

参考:

posted @ 2020-12-08 11:49  gzhjj  阅读(298)  评论(0编辑  收藏  举报