题目链接:LeetCode 239. 滑动窗口最大值
题意:
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
解题思路:
(单调队列) O(n)
使用单调队列求解滑动窗口中的最大值。其中,单调队列是一个普通的双端队列,即队头和队尾都可以添加和弹出元素。我们假设该双端队列的 队头 是整个队列的最大元素所在下标,至 队尾 下标代表的元素值依次降低。
初始时单调队列为空。随着对数组的遍历过程中,每次插入元素前,需要考察两个事情:
(1). 合法性检查:队头下标如果距离 i 超过了 k ,则应该出队。
(2). 单调性维护:如果 nums[i] 大于或等于队尾元素下标所对应的值,则当前队尾再也不可能充当某个滑动窗口的最大值了,故需要队尾出队。始终保持队中元素从队头到队尾单调递减。
如次遍历一遍数组,队头就是每个滑动窗口的最大值所在下标。
时间复杂度
遍历中,每个元素最多进队一次,出队一次,故时间复杂度为 O(n)。
空间复杂度
需要额外 O(n) 的空间存储单调队列。
完整代码如下:
func maxSlidingWindow(nums []int, k int) []int {
// 单调队列的思想 只要右边的数比左边的大,那么左边的就没有意义,可以直接去掉
var q []int //存放滑动窗口中的数的下标
var res []int //存放结果
for i:=0;i<len(nums);i++{
if len(q)>0 && i-k+1 > q[0]{ //i-k+1表示滑动窗口的左边界,左边界的下标大于q[0],说明q[0]应该退出滑动窗口
q = q[1:]
}
for len(q)>0 && nums[i] >= nums[q[len(q)-1]] {
//如果当前nums[i]的值大于队尾 nums[q[len(q)-1]]的值,则删除队尾元素,当前值入队列。
//因为是求滑动窗口最大值,因此如果当前的值比已经在队列中的值小,则永远不可能成为最大值,直接过滤掉即可
q = q[:len(q)-1]
}
q = append(q,i) //将当前元素的下标加入
if i >=k-1{
res = append(res,nums[q[0]])
}
}
return res
}
标签:下标,窗口,nums,队列,最大值,239,滑动,LeetCode
From: https://www.cnblogs.com/lxing-go/p/17399899.html