题目简述:给定一个数组,还有一个k值,代表窗口大小,记录每次窗口中最大的值,最后将最大值放到数组中进行返回。
这一题的描述,大概就是我的思路,可惜最后不能ac(超时),下面放出我的耿直代码。
未能ac代码1
var maxSlidingWindow = function (nums, k) {
if (k === 1) return nums
let res = []
for (let i = 0; i < nums.length; ++i) {
let maxNum = -Infinity
let tail = i + k < nums.length ? i + k : nums.length
if (i + k === nums.length + 1) break
for (let j = i; j < tail; ++j) {
maxNum = Math.max(maxNum, nums[j])
}
res.push(maxNum)
}
return res
};
既然耿直的思路不行,那肯定有巧妙的思路,我想到的就是,记录窗口内最大值maxNum,然后下次进来的数字就跟maxNum进行比较,但是这里还存在一个问题,滑动出去的数字可能是最大数字,那就又要处理这个逻辑了
未能ac代码2
var maxSlidingWindow = function (nums, k) {
if (k === 1) return nums
let res = []
let maxNum = -Infinity
let firstNum = nums[0]
for (let i = 0; i < k; ++i) {
maxNum = Math.max(maxNum, nums[i])
}
res.push(maxNum)
for (let i = k; i < nums.length; ++i) {
if (firstNum === maxNum) {
maxNum = -Infinity
for (let j = i; j > i - k; --j) {
maxNum = Math.max(maxNum, nums[j])
}
} else {
maxNum = Math.max(maxNum, nums[i])
}
firstNum = nums[i - k + 1]
res.push(maxNum)
}
return res
};
这种解法又又又超时了
所以肯定还有更屌的思路
双端队列
使用queue来维护,里面存放的元素是递减数列的索引,队头始终存放当前窗口内最大元素的索引
-
移除不在当前滑动窗口范围内的索引(即队列头部的索引小于
i - k + 1)。 -
移除所有比当前元素小的元素索引(从队列尾部开始),以确保队列中的元素按降序排列。
-
将当前元素的索引添加到队列。
-
当窗口大小达到
k时,记录当前窗口的最大值(即队列头部的元素)。
var maxSlidingWindow = function (nums, k) {
if (k === 1) return nums
let res = []
let queue = []
for (let i = 0; i < nums.length; ++i) {
// 移除不在滑动窗口内的元素
if (queue.length && queue[0] < i - k + 1) {
queue.shift()
}
// 当前元素大于queue里面索引所指向的元素,将小的元素索引出队
while (queue.length && nums[queue[queue.length - 1]] < nums[i]) {
queue.pop()
}
// 将当前索引放入队列
queue.push(i)
// 窗口满足要求时,将queue队头指向的元素放入res中
if (i >= k - 1) {
res.push(nums[queue[0]])
}
}
return res
};