题目描述
给定一个数组 nums,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k
内的数字。滑动窗口每次只向右移动一位。
返回滑动窗口最大值。
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
方案一 暴力傻方法
第一次遇到自己写出的算法时间居然上千ms,震惊至极。而且空间复杂度也很高。给大家讲一讲思路
大家很容易想到的一种方法,就是前K个元素进入窗口以后,我们对它进行排序,然后找到最后一个就可以,随后的nums.length-k个元素,每进入一个,我们就把窗口最前面的那个元素抛出,假如一个新的元素,然后行进重复的操作,排序,找到最后一个。
因为每次排序会改变数组,所以这里你需要一个另外一个数组来存放排序前的数组。在算法的前面你可以进行判断一下,如果k=1,那么你就可以直接返回原数组.nums=[]直接返回空就可以
var maxSlidingWindow = function(nums, k) {
if (nums.length == 0) { return [] }
if (k == 1) return nums
let window = []
let window1 = []
let res = []
for (let i = 0; i < k; i++) {
window.push(nums[i])
}
window1 = window.slice()
window.sort((x, y) => x - y)
res.push(window[k - 1])
for (let i = k; i < nums.length; i++) {
window1.shift()
window1.push(nums[i])
window = window1.slice()
window1.sort((x, y) => x - y)
res.push(window1[k - 1])
window1 = window
}
return res
};
上面算法的复杂度我给大家计算下啊,首先每次进入一个数据,都要进行sort排序,sort用最快的快排,其时间复杂度是nlogn的,进入n个数的话就是n²logn 很大了
方案二 采用双向队列
看题中给的数据
1 3 -1 -3 5 3 6 7
我们给一个窗口队列,来存放进入的数据
首先是1进入,队列为[1],然后3进入,这时候3进入的时候先和它前面的数据进行比较,发现3>1,这时候把队列中1抛出
这时候-1进入队列,发现-1小于3,所以-1进入以后不进行任何操作。这时候队列为[3,-1]这时候其实窗口的大小已经为3啦
因为我们前面抛出一个1所以看着是两个数据。然后-3进入,这时候就要判断,窗口队列的长度是不是大于k,当大于k的时候
就要把队列的首元素抛出。-3进入的时候,明显长度没有超出,所以不用管,然后-3和队尾元素比较,小于队尾。进入队里无操作。
这时候队列是[3,-1,-3],随后5进入,这时候,队列的长度大于k,把队列头元素3抛出,然后进行判断,发现5比队尾元素大,这时候
抛出队尾的-3,这时候队尾元素变成-1,5还是大于-1,继续抛出,这时候队列中只有[5].然后6准备进入。
发现6大于队尾5,5抛出,6进入。7的操作同上。
上面的操作结果为:队列的头元素永远是最大的,所以后面的(nums.length-k)次进入,只需要队列的头放入输出数组即可,代码如下
index为下标,window存放的为下标,item遍历数组中的元素
var maxSlidingWindow = function(nums, k) {
if (nums.length == 0) return []
let window = []//队列用来存放下标
let res = []
nums.forEach((item, index) => {
console.log(window, nums[window[0]])
if (index >= k && window[0] <= index - k) {
window.shift()//队列头抛出
}
while (window && nums[window[window.length - 1]] <= item) {
window.pop()//队列为抛出
}
window.push(index)
if (index >= k - 1) {
res.push(nums[window[0]])
}
})
return res
}