1
+ // 题目链接:https://leetcode.cn/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/?envType=study-plan&id=lcof
2
+ // day27/31
3
+ // 第 27 天主题为:栈与队列(困难)
4
+ // 包含两道题目:
5
+ // 剑指offer59-I.滑动窗口的最大值
6
+ // 剑指offer59-II.队列的最大值
7
+ package main
8
+
9
+ //可以先去暴力解决,对每个滑动窗口,遍历所有元素得到最大值。
10
+ //对长度为 n 的数组 nums,窗口数量为 n-k+1,暴力解法时间复杂度为 O((n-k+1)*k) = O(nk)
11
+ func maxSlidingWindow (nums []int , k int ) []int {
12
+ n := len (nums )
13
+ if n == 0 || k == 0 {
14
+ return []int {}
15
+ }
16
+ res := []int {}
17
+ for i := 0 ;i < n - k + 1 ;i ++ {
18
+ res = append (res ,max (nums [i :i + k ]))
19
+ }
20
+ return res
21
+ }
22
+
23
+
24
+ func max (sli []int ) (res int ){
25
+ res = sli [0 ]
26
+ for _ ,i := range sli {
27
+ if i > res {
28
+ res = i
29
+ }
30
+ }
31
+ return
32
+ }
33
+
34
+ //法二:单调队列
35
+ //然后想一想,暴力没有用到题目中哪些条件,可以针对这些条件去做改进
36
+ //相邻的两个窗口,有重叠元素 k-1 个,这 k-1 个元素中的最大值对两个窗口来说是相同的,这就是我们改进的方向
37
+ //
38
+ //设想一下,一个窗口中两个元素下标分别为 i 和 j,其中 i 在 j 的左侧(i<j)
39
+ //- 若 nums[i] < nums[j],在滑动窗口右移的过程中,只要 nums[i] 在窗口中,则 nums[j] 也一定还在窗口中,这是 i<j 所保证的。
40
+ // 因此,由于 nums[j] 的存在,nums[i] 一定不会是滑动窗口最大值,我们可以将 nums[i] 永久删除。
41
+ //- 若 nums[i] >= nums[j],nums[i] 出队后,nums[j] 是有可能成为队列最大值的,nums[j] 需要保留
42
+ //
43
+ //因此,我们可以使用一个队列来存储还没有被删除的元素。在队列中,这些元素的值是单调递减的
44
+ //当窗口向右滑动时,我们需要把一个新的元素放入队列中,为了保持队列的性质,我们需要不断将新元素与队列队尾元素进行比较,
45
+ //若新元素较大,则队尾元素出队,不断进行此操作,直至队列为空 或 新的元素小于等于队尾的元素
46
+ //
47
+ //由于队列的元素是严格单调递减的,且队列中元素属于该窗口,所以队首元素就是该窗口的最大值
48
+ //此时,我们需要考虑最后一个问题,若当前窗口的最大值为窗口最左侧元素,那进入下一个窗口前队列中该元素应该出队,因为该元素并不属于下一个窗口
49
+ //
50
+ //该队列元素单调递减,满足这种单调性的队列一般称作 单调队列。
51
+ func maxSlidingWindow_2 (nums []int , k int ) []int {
52
+ n := len (nums )
53
+ monoQ := []int {}
54
+ res := make ([]int ,0 ,n - k + 1 )
55
+ for i := 0 ;i < n ;i ++ {
56
+ for len (monoQ ) > 0 && nums [i ] > monoQ [len (monoQ )- 1 ]{
57
+ monoQ = monoQ [:len (monoQ )- 1 ]
58
+ }
59
+ monoQ = append (monoQ ,nums [i ])
60
+ // 若单调队列最大值非窗口元素
61
+ // 将该元素出队
62
+ if i >= k && monoQ [0 ] == nums [i - k ]{
63
+ monoQ = monoQ [1 :]
64
+ }
65
+ // i=k-1时,窗口元素数量达到 k
66
+ // 开始向 res 数组添加窗口最大值
67
+ if i >= k - 1 {
68
+ res = append (res ,monoQ [0 ])
69
+ }
70
+ }
71
+ return res
72
+ }
0 commit comments