返回
剑指 Offer——I. 滑动窗口的最大值(JavaScript 实现)
前端
2023-10-12 21:20:38
剑指 Offer——I. 滑动窗口的最大值
给定一个整数数组和一个窗口大小 k,请找出所有滑动窗口里的最大值。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
示例 2:
输入:nums = [1], k = 1
输出:[1]
提示:
- 1 <= nums.length <= 10^5
- -10^4 <= nums[i] <= 10^4
- 1 <= k <= nums.length
解题思路
暴力法
暴力法就是定义一个滑动窗口,然后通过循环不断地去移动这个窗口,直到窗口走到最后,然后分别求出每一个窗口的最大值,存到最终结果数组中,最后返回
虽然通过暴力法也能够通过,但是时间复杂度非常高,达到了 O(nk),其中 n 是数组的长度,k 是窗口的大小。
滑动窗口解法
滑动窗口解法是使用一个双端队列来维护一个大小为 k 的窗口,然后通过不断地将窗口向后移动,来得到窗口中最大的值。
具体步骤如下:
- 初始化一个双端队列 deque,将窗口内的元素从小到大依次加入到 deque 中。
- 将窗口向后移动一位,并将 deque 中最小的元素弹出。
- 将窗口中最大的元素加入到 deque 中。
- 重复步骤 2 和步骤 3,直到窗口移动到最后。
- 将 deque 中的元素依次取出,即为窗口中的最大值。
JavaScript 实现
/**
* 求滑动窗口的最大值
* @param {number[]} nums 数组
* @param {number} k 滑动窗口大小
* @return {number[]} 滑动窗口中的最大值
*/
const maxSlidingWindow = (nums, k) => {
if (nums === null || nums.length === 0 || k <= 0 || k > nums.length) {
throw new Error("Invalid input!");
}
const deque = [];
const result = [];
for (let i = 0; i < nums.length; i++) {
// 将 deque 中比当前元素小的元素弹出
while (deque.length > 0 && nums[deque[deque.length - 1]] < nums[i]) {
deque.pop();
}
// 将当前元素加入到 deque 中
deque.push(i);
// 当窗口向后移动一位时,将 deque 中最小的元素弹出
if (i >= k - 1) {
result.push(nums[deque[0]]);
if (deque[0] === i - k + 1) {
deque.shift();
}
}
}
return result;
};
复杂度分析
- 时间复杂度:O(n),其中 n 是数组的长度。
- 空间复杂度:O(k),其中 k 是窗口的大小。
结语
滑动窗口是一种重要的算法技术,在很多场景中都有应用。在本文中,我们介绍了滑动窗口的实现原理和应用场景,并通过 JavaScript 实现了一个滑动窗口算法,来求解剑指 Offer——I. 滑动窗口的最大值。如果您对滑动窗口算法感兴趣,可以参考本文来实现自己的滑动窗口算法。