题目

给定一个数组 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

提示:
你可以假设 k 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。

方案一

  1. type maxNums struct {
  2. window []int
  3. k int
  4. // 当前窗口的最大值
  5. max int
  6. // 当前窗口最大值的个数
  7. max_count int
  8. maxes []int
  9. }
  10. func (m *maxNums) add(num int) {
  11. head := m.window[0]
  12. m.window = m.window[1:]
  13. m.window = append(m.window, num)
  14. if num == m.max {
  15. if head != num {
  16. m.max_count++
  17. }
  18. m.maxes = append(m.maxes, num)
  19. }
  20. if num > m.max {
  21. m.max = num
  22. m.max_count = 1
  23. m.maxes = append(m.maxes, m.max)
  24. }
  25. if num < m.max {
  26. // head 不可能大于 m.max
  27. if head == m.max {
  28. m.max_count--
  29. if m.max_count == 0 {
  30. m.setMaxAndMaxCountUseWindow()
  31. }
  32. }
  33. m.maxes = append(m.maxes, m.max)
  34. }
  35. }
  36. func (m *maxNums) init(nums []int) {
  37. m.window = nums
  38. m.setMaxAndMaxCountUseWindow()
  39. m.maxes = append(m.maxes, m.max)
  40. }
  41. func (m *maxNums) setMaxAndMaxCountUseWindow() {
  42. m.max = m.window[0]
  43. for _, num := range m.window {
  44. if m.max == num {
  45. m.max_count++
  46. }
  47. if m.max < num {
  48. m.max = num
  49. m.max_count = 1
  50. }
  51. }
  52. }
  53. func maxSlidingWindow(nums []int, k int) []int {
  54. if len(nums) == 0 {
  55. return []int{}
  56. }
  57. maxNums := &maxNums{
  58. window: make([]int, len(nums)),
  59. k: k,
  60. maxes: []int{},
  61. // 初始化 max 为 min
  62. max: -1 << 31,
  63. }
  64. maxNums.init(nums[:k])
  65. for i := k; i < len(nums); i++ {
  66. maxNums.add(nums[i])
  67. }
  68. return maxNums.maxes
  69. }

方案二(单调队列)

func maxSlidingWindow(nums []int, k int) []int {
    res := []int{}
    window := []int{}

    // 维护单调递减的 window
    for i := 0; i < len(nums); i++ {
        if i-k < 0 {
            window = append(window, nums[i])
            if nums[i] > window[0] {
                window = []int{nums[i]}
            }
            continue
        }
        res = append(res, window[0])

        if nums[i] > window[0] {
            window = []int{nums[i]}
            continue
        }
        window = append(window, nums[i])
        if len(window) > k {
            index := getFirstMaxNumIndex(window[1:])
            window = window[1:][index:]
        }
    }

    if len(window) > 0 {
        res = append(res, window[0])
    }

    return res
}

func getFirstMaxNumIndex(nums []int) int {
    if len(nums) == 0 {
        return 0
    }

    max, index := nums[0], 0
    for i, num := range nums {
        if num > max {
            max = num
            index = i
        }
    }

    return index
}

原文

https://leetcode-cn.com/leetbook/read/illustrate-lcof/5iy0oi/
https://leetcode-cn.com/leetbook/read/illustrate-lcof/5iba5g/