第三节:队列相关(滑动窗口最大值、)

一. 滑动窗口最大值

一. 题目描述

    给你一个整数数组 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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2024-03-07 10:40  Yaopengfei  阅读(3)  评论(0编辑  收藏  举报