第三节:队列相关(滑动窗口最大值、)
一. 滑动窗口最大值
一. 题目描述
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。
滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。(求的是窗口每次移动中的最大值,最后组成的一个数组)
详见:https://leetcode.cn/problems/sliding-window-maximum/description/
难度:【困难】
示例:详见leetcode图
二. 思路分析-方案1(暴力求解)
1 .大纲:遍历求每次窗口对应数组中的最大值 (暴力求解,不推荐)
2. 核心要点:
A. 滑动窗口出现的次数:nums.length - k + 1
B. slice截取数组:[) 闭开区间
剖析该方案:好理解,但是非常耗费性能当数据量大的时候!!! (leetcode上这套方案不通过)
/**
* 滑动窗口--方案1
* @param nums 数组
* @param k 窗口中的个数
* @returns 每次窗口移动最大值组成的数组
*/
function maxSlidingWindow0(nums: number[], k: number): number[] {
let resMax: number[] = []; //存放结果的数组
let len = nums.length;
let slideCount = len - k + 1; //窗口总共出现的次数
for (let i = 0; i < slideCount; i++) {
let slideNum = nums.slice(i, i + k); //窗口中的数组 [)
let max = Math.max(...slideNum);
resMax.push(max);
}
return resMax;
}
三. 思路分析-方案2
(1). 创建一个双端队列(数组) 【ps:插入都是尾部push,删除可能头部shift,也可能尾部pop】
(2). 遍历每一个元素
(3). 判断队列中元素是否符合单调递减的条件,且当前元素要比队尾元素小 不符合,则删除队尾元素。
(4).将该元素的"索引"插入队列
(5). 判断队列中的队首元素是否在滑动窗口中,不在的话,则删除队首元素
剖析:
举例说明:nums=[3,1,-1,-3,5,3,6,7],k=3
当i=3的时候,队列中的元素依次为:【3,1,-1,-3】,现在的最大值是3,但是它已经不再滑动窗口内了
滑动窗口内的元素为:【1,-1,-3】 即 【i-k+1,i】
所以下面的条件是: deque[0]<i-k+1 更好理解,或者写成 deque[0]<=i-k,也是可以的。
(6). 获取队首的最大元素,插入到结果集中,必须满足滑动窗口生效后,才能获取
剖析:
分析:假设k=3,即i>=2,才能取队列中的最大值
i>=2,说明的是 必须等滑动窗口生效才行, i=2的时候,即滑动窗口第1次生效 [0,2]
/**
* 滑动窗口--方案2
* @param nums 数组
* @param k 窗口中的个数
* @returns 每次窗口移动最大值组成的数组
*/
function maxSlidingWindow(nums: number[], k: number): number[] {
//1.声明数据
let n = nums.length;
let deque: number[] = []; //双端队列
let resMax: number[] = []; //存放最大值结果的数据
//遍历每个元素
for (let i = 0; i < n; i++) {
//3 判断队列中元素是否符合单调递减的条件,且当前元素要比队尾元素小
while (deque.length && nums[i] > nums[deque[deque.length - 1]]) {
deque.pop();
}
//4.将该元素的"索引"插入队列
deque.push(i);
//5.判断队列中的队首元素是否在滑动窗口中,不在的话,则删除队首元素
while (deque[0] < i - k + 1) {
deque.shift();
}
//6.获取队首的最大元素,插入到结果集中,
//必须满足滑动窗口生效后,才能获取
if (i >= k - 1) {
resMax.push(nums[deque[0]]);
}
}
return resMax;
}
//测试
console.log(maxSlidingWindow([1, 3, -1, -3, 5, 3, 6, 7], 3)); //[ 3, 3, 5, 5, 6, 7 ]
console.log(maxSlidingWindow([2], 1)); //[2]
二.
三.
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。