You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
var maxSlidingWindow = function (nums, k) {
let result = [];
for (let i = 0; i <= nums.length - k; i++) {
let item = Math.max(...nums.slice(i, k + i))
result.push(item);
}
return result;
};
function getMaxSlidingWindow(nums, k) {
let res = [Math.max(...nums.splice(0, k))]
if (nums.length === k) {
return res
}
for (let i = 0, len = nums.length; i < len; i++) {
let curMax = res[res.length - 1];
console.log(res, curMax)
curMax = curMax >= nums[i] ? curMax : nums[i]
res.push(curMax)
}
return res
}
varmaxSlidingWindow=function(nums,k){// bad 时间复杂度O(n * k)if(nums.length===0||k===0)return[];letslideWindow=[];constret=[];for(leti=0;i<nums.length-k+1;i++){for(letj=0;j<k;j++){slideWindow.push(nums[i+j]);}ret.push(Math.max(...slideWindow));slideWindow=[];}returnret;};
Activity
7777sea commentedon May 7, 2020
loknum commentedon May 7, 2020
2384830985 commentedon May 7, 2020
var maxSlidingWindow = function(nums, k) {
let axx = []
let fun = function(){
let arr = nums.slice(0,k)
axx.push(Math.max(...arr))
}
fun()
while(nums.length>k){
nums.shift()
fun()
}
return axx
};
zhangxiaos commentedon May 7, 2020
zhaojinzhao commentedon May 7, 2020
nums.slice(0, 1 - k).map((v, index) => Math.max(...nums.slice(index, index + k)));
Ttomsjson commentedon May 7, 2020
var ss = function(num,k) {
if(!Array.isArray(num) || k <= 0) return
}
var aa = [1,3,-1,-3,5,3,6,7];
var k = 3;
ss(aa,k)
teal-front commentedon May 7, 2020
sisterAn commentedon May 7, 2020
解答一:暴力解法
复杂度分析:
时间复杂度:O(n*k)
空间复杂度:O(n)
解答二:优化:双端队列
解题思路: 使用一个双端队列存储窗口中值的 索引 ,并且保证双端队列中第一个元素永远是最大值,那么只需要遍历一次
nums,就可以取到每次移动时的最大值。i和双端队列第一个元素(索引值),相差 >= k 时队首出列result中代码实现:
复杂度分析:
leetcode
zjhlaap commentedon Jul 20, 2020
AnranS commentedon Nov 14, 2020
azl397985856 commentedon Mar 3, 2021
题目地址(239. 滑动窗口最大值)
https://leetcode-cn.com/problems/sliding-window-maximum/
题目描述
前置知识
公司
思路
符合直觉的想法是直接遍历 nums, 然后然后用一个变量 slideWindow 去承载 k 个元素,$N$ ,k 个元素求最大值时间复杂度是 $k$ , 因此总的时间复杂度是 O(n * k).代码如下:
然后对 slideWindow 求最大值,这是可以的,遍历一次的时间复杂度是
JavaScript:
Python3:
但是如果真的是这样,这道题也不会是 hard 吧?这道题有一个 follow up,要求你用线性的时间去完成。
其实,我们没必须存储窗口内的所有元素。 如果新进入的元素比前面的大,那么前面的元素就不再有利用价值,可以直接移除。这提示我们使用一个单调递增栈来完成。
但由于窗口每次向右移动的时候,位于窗口最左侧的元素是需要被擦除的,而栈只能在一端进行操作。
而如果你使用数组实现,就是可以在另一端操作了,但是时间复杂度仍然是$O(k)$ ,和上面的暴力算法时间复杂度一样。
因此,我们考虑使用链表来实现,维护两个指针分别指向头部和尾部即可,这样做的时间复杂度是$O(1)$ ,这就是双端队列。
因此思路就是用一个双端队列来保存
接下来的滑动窗口可能成为最大值的数。具体做法:
一种是已经超出窗口范围了,比如我遍历到第 4 个元素,k = 3,那么 i = 0 的元素就不应该出现在双端队列中了
具体就是
索引大于 i - k + 1的元素都应该被清除小于当前元素都没有利用价值了,具体就是
从后往前遍历(双端队列是一个递减队列)双端队列,如果小于当前元素就出队列经过上面的分析,不难知道双端队列其实是一个递减的一个队列,因此队首的元素一定是最大的。用图来表示就是:
关键点解析
双端队列简化时间复杂度
滑动窗口
代码
JavaScript:
JS 的 deque 实现我这里没有写, 大家可以参考 collections/deque
复杂度分析
Python3:
复杂度分析
扩展
为什么用双端队列
因为删除无效元素的时候,会清除队首的元素(索引太小了)或者队尾(元素太小了)的元素。 因此需要同时对队首和队尾进行操作,使用双端队列是一种合乎情理的做法。
大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。
大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
JohnApache commentedon Apr 29, 2021
这一题用了两种方案,
第一种方案算是暴力写法,也是大多数人常规思路
第二种方案是用了 基于队列的方式 其实,我们没必须存储窗口内的所有元素。 如果新进入的元素比前面的大,那么前面的元素就不再有利用价值,可以直接移除,这样队列对应的值其实就是一个单调递减的队列,
暴力写法
思路清晰,但是代码时间复杂度高 Om*n
队列
队列保存的是在原数组的索引位置,是为了方便控制当窗口移动时,需要删除索引小于
i - k后的数字,然后每次存储新的索引前队列中推出所有比当前数字小的值的索引,这样每次循环 在i >= k -1时存储队列的第一个值索引对应的数字,最终返回结果即可,我这里用双向链表自己实现了一个方便自己操作的首位数据的队列数据结构