528 字
3 分钟
LeetCode-239.滑动窗口最大值
滑动窗口
给你一个整数数组
nums,有一个大小为k的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k个数字。滑动窗口每次只向右移动一位。返回 滑动窗口中的最大值 。
示例 1:
输入: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 31 [3 -1 -3] 5 3 6 7 31 3 [-1 -3 5] 3 6 7 51 3 -1 [-3 5 3] 6 7 51 3 -1 -3 [5 3 6] 7 61 3 -1 -3 5 [3 6 7] 7示例 2:
输入:nums = [1], k = 1输出:[1]
1.自己的失败的解法
只有42/52通过了测试用例,超出时间限制了🥲
func maxSlidingWindow(nums []int, k int) []int { right := 0 window := []int{} res := []int{}
if len(nums) < k { return nums }
for right < len(nums) { window = append(window, nums[right]) maxVal := window[0]
if len(window) == k { for _, val := range window { if val > maxVal { maxVal = val } }
res = append(res, maxVal) window = window[1:] } right++ } return res}2.滑动窗口 + 单调对列
评论区找到的地狱故事挺好地解释了这个算法
这是一个降本增笑的故事:
- 如果新员工比老员工强(或者一样强),把老员工裁掉。(元素进入窗口)
- 如果老员工 35 岁了,也裁掉。(元素离开窗口)
裁员后,资历最老(最左边)的人就是最强的员工了。
思路:我们需要降低时间复杂度,之前的时间复杂度是 O(N×k),为了把时间复杂度降到 O(N),我们需要一种特殊的数据结构,它需要满足:队头永远是当前窗口的最大值
func maxSlidingWindow(nums []int, k int) []int { if len(nums) == 0 || k == 0 { return []int{} }
var deque []int var res []int
for right := 0; right < len(nums); right++ {
for len(deque) > 0 && nums[deque[len(deque)-1]] < nums[right] { deque = deque[:len(deque)-1] }
deque = append(deque, right)
if deque[0] < right - k + 1 { deque = deque[1:] }
if right >= k - 1 { res = append(res, nums[deque[0]]) } } return res} LeetCode-239.滑动窗口最大值
https://sheep44044.github.io/posts/算法/滑动窗口/leetcode-239滑动窗口最大值/