时间复杂度:O(n)
解题思路
该题用的是双端队列。
该双端队列存放的是nums的索引,严格按照索引对应元素从大到小排序,且两端均可出队。
当一个索引入队时,我们要比较该索引对应值与双端队列末尾对应值的大小,如果前者较大那么我们需要删除掉末尾索引,重复此过程直到数组为空或者遇到比它大的值。
此外我们还需要注意当随着滑动窗口的移动,双端队列存放的索引可能会不在滑动窗口中,特别是当双端队列头部索引不在滑动窗口中时,我们必须要使其出队,让第二个大的索引顶上去。
按照此规则,我们可以先让滑动窗口初始位置的所有索引入队,完事后的队列头部索引对应值就是第一个滑动窗口的最大值。接下来随着滑动窗口的滑动,将每个新索引入队,并让不在滑动窗口中的头部索引出队,此时滑动窗口的最大值就是双端队列头部索引的对应值。
AC代码
func maxSlidingWindow(nums []int, k int) []int {
q:=[]int{}//双端队列,保存的是索引
//添加索引到双端队列中的push函数
push:=func(x int){
for len(q)>=1&&nums[x]>=nums[q[len(q)-1]]{
q=q[:len(q)-1]//去除队列中小于nums[X]的对应索引
}
q=append(q,x)//索引入队
}
//第一个滑动窗口的元素索引单独入队
for i:=0;i<k;i++{
push(i)
}
res:=make([]int,1,len(nums)-k+1)
res[0]=nums[q[0]]
for i:=k;i<len(nums);i++{
//最大值的索引不在滑动窗口内了
if q[0]==i-k{
q=q[1:]//第二大索引继位
}
push(i)
res=append(res,nums[q[0]])
}
return res
}
感悟
原先接触的是单调栈,这次是双端队列,总有异曲同工之妙。仔细想一想,对于这种要找最大值最小值的题,貌似都可以考虑一下双端队列和单调栈。