题解:

这道题比较经典,我们可以采用队列,DP,堆等方式进行求解,所有思路的主要源头应该都是在窗口滑动的过程中,如何更快的完成查找最大值的过程。但是最典型的解法还是使用双端队列。具体怎么来求解,一起看一下。

首先,我们了解一下,什么是双端队列:是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出或者插入。
滑动窗口最大值(239) - 图1

我们可以利用双端队列来实现一个窗口,目的是让该窗口可以做到张弛有度(汉语博大精深,也就是长度动态变化。其实用游标或者其他解法的目的都是一样的,就是去维护一个可变长的窗口)

然后我们再做一件事,只要遍历该数组,同时在双端队列的头去维护当前窗口的最大值(在遍历过程中,发现当前元素比队列中的元素大,就将原来队列中的元素祭天),在整个遍历的过程中我们再记录下每一个窗口的最大值到结果数组中。最终结果数组就是我们想要的,整体图解如下。

假设 nums = [1,3,-1,-3,5,3,6,7],和 k = 3
滑动窗口最大值(239) - 图2

根据分析,得出代码:

  1. func maxSlidingWindow(nums []int, k int) []int {
  2. if len(nums) == 0 {
  3. return []int{}
  4. }
  5. //用切片模拟一个双端队列
  6. queue := []int{}
  7. result := []int{}
  8. for i := range nums {
  9. for i > 0 && (len(queue) > 0) && nums[i] > queue[len(queue)-1] {
  10. //将比当前元素小的元素祭天
  11. queue = queue[:len(queue)-1]
  12. }
  13. //将当前元素放入queue中
  14. queue = append(queue, nums[i])
  15. if i >= k && nums[i-k] == queue[0] {
  16. //维护队列,保证其头元素为当前窗口最大值
  17. //判断是否还在最大值的范围,不在就把失效的最大值弹出
  18. //即如果队列中的最大值已经不在次滑动窗口内,就将其弹出
  19. queue = queue[1:]
  20. }
  21. if i >= k-1 {
  22. //放入结果数组
  23. result = append(result, queue[0])
  24. }
  25. }
  26. return result
  27. }

参考:

https://www.geekxh.com/1.5.%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3%E7%B3%BB%E5%88%97/501.html#_03%E3%80%81%E7%BA%BF%E6%80%A7%E9%A2%98%E8%A7%A3