滑动窗口的最大值
难度困难
给定一个数组 nums 和滑动窗口的大小 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
此题有各种差解和次优解,最优解是单调队列,是一个动态的单调队列,遍历过程会操作这个单调队列,保证:
- 队列单调递减
- 队列头最大值的下标如果滑出窗口最小下标就移出队列
也就是保存了上一个窗口最大的值,和次大的值,和次次大的值,如果最大移出了,也能取到次大的值,来构建新的队列。
滑动窗口的位置 单调队列
--------------- -----
[1 3 -1] -3 5 3 6 7 3 -1
1 [3 -1 -3] 5 3 6 7 3 -1 -3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5 3
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
代码如下:
class Solution {
fun maxSlidingWindow(nums: IntArray, k: Int): IntArray {
var result = IntArray(nums.size - k + 1)
var list = LinkedList<Int>()
for (i in 0..nums.size - 1) {
//队列头最大值的下标如果滑出窗口最小下标就移出队列
if (!list.isEmpty() && list.first < i - k + 1) {
list.removeFirst()
}
//队列单调递减
while (!list.isEmpty() && nums[list.last] < nums[i]) {
list.removeLast()
}
list.add(i)
if (i >= k - 1) {
result[i - k + 1] = nums[list.first]
}
}
return result;
}
}