Featured image of post maxSlidingWindow

maxSlidingWindow

239. 滑动窗口最大值

算法

  1. 维护一个单调递减队列:

    • 使用一个双端队列 q 存储数组的索引
    • 队列中的元素对应的值保持单调递减顺序,队首始终是当前窗口的最大值索引
  2. 窗口滑动的处理:

    • 窗口失效处理:检查队首索引是否超出当前窗口范围 (i - k + 1),若超出则弹出队首
    • 保持单调性:将新元素加入队列时,弹出队列中所有小于当前元素值的索引,以确保队列的单调递减性
    • 记录最大值:当窗口的大小达到 k(i >= k - 1),窗口的最大值即为队首索引对应的值

复杂度分析

时间复杂度

  • 遍历数组:所有元素仅被插入和弹出队列一次,时间复杂度为 O(n)
  • 队列操作:每次插入和弹出操作的平均时间复杂度为 O(1)
  • 总时间复杂度:O(n)

空间复杂度

  • 使用了一个双端队列存储索引,空间复杂度为 O(k)

C++ 代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution
{
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k)
    {
        std::deque<int> q;            // 双端队列存储索引
        std::vector<int> res;         // 存储结果

        for (int i = 0; i < nums.size(); ++i)
        {
            // 移除队首超出窗口范围的元素
            if (q.size() && q.front() < i - k + 1)
                q.pop_front();

            // 保持队列单调递减
            while (q.size() && nums[q.back()] <= nums[i])
                q.pop_back();

            // 添加当前元素索引到队列
            q.push_back(i);

            // 当窗口形成时,记录窗口最大值
            if (i >= k - 1)
                res.push_back(nums[q.front()]);
        }

        return res;
    }
};

Python 代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from collections import deque

class Solution:
  def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
    dq = deque()
    res = []

    for i in range(len(nums)):
      while dq and nums[dq[-1]] <= nums[i]:
        dq.pop()

      if dq and dq[0] < i - k + 1:
        dq.popleft()

      dq.append(i)

      if i >= k - 1:
        res.append(nums[dq[0]])

    return res

Go 代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func maxSlidingWindow(nums []int, k int) []int {
  dq := []int{}
  res := []int{}

  for i := 0; i < len(nums); i ++ {
    for len(dq) > 0 && nums[dq[len(dq) - 1]] <= nums[i] {
      dq = dq[:len(dq) - 1]
    }
    if len(dq) > 0 && dq[0] < i - k + 1 {
      dq = dq[1:]
    }
    dq = append(dq, i)

    if i >= k - 1 {
      res = append(res, nums[dq[0]]);
    }
  }

  return res;
}

JavaScript 代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var maxSlidingWindow = function (nums, k) {
  let dq = [],
    res = [];
  for (let i = 0; i < nums.length; i++) {
    while (dq.length && nums[dq[dq.length - 1]] <= nums[i]) {
      dq.pop();
    }

    if (dq.length && dq[0] < i - k + 1) {
      dq.shift();
    }

    dq.push(i);

    if (i >= k - 1) {
      res.push(nums[dq[0]]);
    }
  }
  return res;
};
Built with Hugo
Theme Stack designed by Jimmy