跳至主要內容

Mr.He大约 2 分钟

方案一:暴力解法(修正你的代码)

var maxSlidingWindow = function(nums, k) {
    if (k >= nums.length) return [Math.max(...nums)];
    
    const result = [];
    let left = 0, right = k - 1;
    
    while (right < nums.length) {
        // 使用 slice 获取窗口(不修改原数组),然后求最大值
        const window = nums.slice(left, right + 1);
        result.push(Math.max(...window));
        left++;
        right++;
    }
    
    return result;
};

方案二:单调队列(最优解,O(n))

=== 单调队列解法原理 ===

维护一个单调递减的双端队列(存索引)
队列特点:
  1. 队列只维护索引,队首永远是当前窗口最大值的索引
  2. 新元素入队前,先移除所有比它小的元素
  3. 移除已出窗口的元素(队首索引 < i-k+1)

--- 处理 nums[0] = 1 ---
  入队索引 0,队列: [0]

--- 处理 nums[1] = 3 ---
  移除队尾 0(值 1 < 3)
  入队索引 1,队列: [1]

--- 处理 nums[2] = -1 ---
  入队索引 2,队列: [1, 2]
  窗口: [1, 3, -1], 最大值: 3 (索引 1)

--- 处理 nums[3] = -3 ---
  入队索引 3,队列: [1, 2, 3]
  窗口: [3, -1, -3], 最大值: 3 (索引 1)

--- 处理 nums[4] = 5 ---
  移除队首 1(已出窗口)
  移除队尾 3(值 -3 < 5)
  移除队尾 2(值 -1 < 5)
  入队索引 4,队列: [4]
  窗口: [-1, -3, 5], 最大值: 5 (索引 4)

--- 处理 nums[5] = 3 ---
  入队索引 5,队列: [4, 5]
  窗口: [-3, 5, 3], 最大值: 5 (索引 4)

--- 处理 nums[6] = 6 ---
  移除队尾 5(值 3 < 6)
  移除队尾 4(值 5 < 6)
  入队索引 6,队列: [6]
  窗口: [5, 3, 6], 最大值: 6 (索引 6)

--- 处理 nums[7] = 7 ---
  移除队尾 6(值 6 < 7)
  入队索引 7,队列: [7]
  窗口: [3, 6, 7], 最大值: 7 (索引 7)

最终结果: [3, 3, 5, 5, 6, 7]

/**
 * 单调队列解法(推荐)
 * 时间复杂度: O(n)
 */
var maxSlidingWindow = function(nums, k) {
    if (k >= nums.length) return [Math.max(...nums)];
    
    const result = [];
    const deque = [];  // 双端队列,存储索引
    
    for (let i = 0; i < nums.length; i++) {
        // 1. 移除已出窗口的元素(队首索引 < i-k+1)
        while (deque.length > 0 && deque[0] < i - k + 1) {
            deque.shift();
        }
        
        // 2. 移除比当前元素小的元素(维护单调递减)
        while (deque.length > 0 && nums[deque[deque.length - 1]] < nums[i]) {
            deque.pop();
        }
        
        // 3. 当前索引入队
        deque.push(i);
        
        // 4. 窗口形成后,记录最大值(队首)
        if (i >= k - 1) {
            result.push(nums[deque[0]]);
        }
    }
    
    return result;
};

复杂度对比

方法时间复杂度空间复杂度
暴力解法O(n×k)O(1)
单调队列O(n)O(k)
单调队列的核心思想:每个元素最多入队一次、出队一次,所以总时间复杂度是 O(n)!