返回

LeetCode题解:239. 滑动窗口最大值,暴力算法与优化详解,JavaScript实现

前端

导言

滑动窗口问题是一种常见的数据结构和算法问题,涉及在一个数据序列的子集(窗口)上进行操作,并随着窗口在序列中移动而更新结果。在“滑动窗口最大值”问题中,我们的目标是找到给定序列中所有可能滑动窗口的最大值。

暴力算法

暴力算法采用双重循环枚举所有可能的滑动窗口,计算每个窗口的最大值。它的时间复杂度为O(n^2),其中n是序列的长度。虽然简单易懂,但当n较大时,效率低下。

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
const maxSlidingWindow = function(nums, k) {
  const result = [];
  
  // 遍历每个滑块的起始点
  for (let i = 0; i <= nums.length - k; i++) {
    let max = nums[i];
    
    // 遍历后续滑块元素
    for (let j = i + 1; j < i + k; j++) {
      if (nums[j] > max) {
        max = nums[j];
      }
    }
    
    result.push(max);
  }
  
  return result;
};

优化算法

优化算法使用一个单调队列(双端队列)来跟踪窗口中元素的递减顺序。当窗口移动时,单调队列可以高效地维护窗口中的最大值。时间复杂度降至O(n)。

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
const maxSlidingWindow = function(nums, k) {
  const result = [];
  const deque = [];
  
  // 遍历数组
  for (let i = 0; i < nums.length; i++) {
    // 移除deque中所有小于当前元素的元素
    while (deque.length && nums[deque[deque.length - 1]] < nums[i]) {
      deque.pop();
    }
    
    // 将当前元素加入deque
    deque.push(i);
    
    // 如果队首元素不在当前窗口中,则移除
    if (deque[0] <= i - k) {
      deque.shift();
    }
    
    // 当窗口长度达到k时,将队首元素加入结果
    if (i >= k - 1) {
      result.push(nums[deque[0]]);
    }
  }
  
  return result;
};

比较

算法 时间复杂度 空间复杂度
暴力算法 O(n^2) O(1)
优化算法 O(n) O(k)

优化算法在时间复杂度方面具有显着优势,尤其是在序列长度较大时。

总结

本文介绍了两种解决LeetCode题解第239题“滑动窗口最大值”的算法:暴力算法和优化算法。我们使用JavaScript进行了代码实现,并提供了详细的注释,以帮助理解算法的实现细节。优化算法通过使用单调队列大大提高了效率,并降低了时间复杂度至O(n)。希望这篇文章能帮助你深入理解滑动窗口问题和算法实现。