Description
You are given an array of integers 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.
Examples
Example 1:
Input: nums = [1,3,-1,-3,5,3,6,7], 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
Example 2:
Input: nums = [1], k = 1
Output: [1]
Constraints:
1 <= nums.length <= 1 0 5 10^5 105
− 1 0 4 -10^4 −104 <= nums[i] <= 1 0 4 10^4 104
1 <= k <= nums.length
思路
作为一道hard,他一定不能用暴力的方式求解,我在solution里面看到了一很很很精妙的方法。
他首先根据k的大小把nums进行分段,以Example1为例,就分为
1 | 3 -1 -3 | 5 3 6 | 7
如此划分之后,再从左到右依次计算每个段落中的最大值
left = 1 | 3 3 3 | 5 5 6 | 7
再从右到左以此计算每个段落中的最大值
right = 1 | 3 -1 -3 | 6 6 6 | 7
当我们要获取以 i
位置为开头的最大值时候,只需要比较 right[i]
和left[i+k-1]
,然后选取较大的那个即可。
可以这么做的原因在于,通过k来划分之后,一个sliding window最多会跨越两个段落,还是以example1为例,i = 3
时,需要判定的是[-3 5 3]
,跨越的就是[3 -1 -3]
和[5 3 6]
,对这两个段落来说,我们之前计算的 right[3] = -3
表示段落1[3 -1 -3]
中,max([-3])
的值,left[3 + 3 - 1] = left[5] = 5
表示段落2[5 3 6]
中,max([5, 3])
的值,那么max(max([-3]), max([5, 3]))
就是 max([-3, 5, 3])
,从而得到sliding window的max值
代码
class Solution {
public int[] maxSlidingWindow(int[] arr, int k) {
int n = arr.length;
int[] left = new int[n];
int[] right = new int[n];
left[0] = arr[0];
for(int i = 1; i < n; i++) {
left[i] = i % k == 0? arr[i]: Math.max(left[i - 1], arr[i]);
}
right[n - 1] = arr[n - 1];
for (int i = n - 2; i >= 0; i--) {
right[i] = i % k == 0? arr[i]: Math.max(right[i + 1], arr[i]);
}
int[] res = new int[n - k + 1];
for(int i = 0; i < n - k + 1; i++)
res[i] = Math.max(right[i], left[i + k - 1]);
return res;
}
}