1. 关于常用方法的介绍,在一个区间内寻找最大值或者最小值。
题目链接:154. 滑动窗口 - AcWing题库
举例,在一个长度为s数组中,窗口的大小为k,窗口从最左侧开始进行移动,输出窗口中最大和最小的两个元素。
2. 思考,在窗口的移动过程中,不断有旧的元素消失,新的元素进来,即先进先出,符合队列的特征。
从暴力的角度来看,每个窗口中找一遍即可,然而当窗口过大,数组过长时,时间会超时。
3. 分析,数组如下:
4 3 8 7 5 6 , 窗口大小为3。
我们首先来寻找窗口中的最小值。
首先4进入窗口。
接着是3,可以思考一下这个时候。4已经在窗口中了,4 大于 3 ,如果3进入窗口,那么4是否还有存在的必要呢?就是3在4的后面进入,并且3小于4,那么在窗口的移动过程中,4一定会首先滑出窗口。而且,4也没有可能会被当做最小值进行输出,那么,我们可以选择将4扔出。
所以我们可以总结出一下规律,如果要进入的数字比在窗口中的数字要小,就需要将窗口中的这个数字扔出。
结合第二点中的队列特点,即在比较和扔出过后,要进入的数字一定比当前窗口中最近的数字大,所以说,这是一个单调递增的队列,当我们想要求取窗口中的最小值时,只需要判断在“合法”的情况下输出队头元素即可。
4. 接下来我们进行分析什么样的情况下合法。
(1)不能是空队列。
(2)我们从第一个元素开始进入,那么我们必须要最少总共进入过一个窗口后才可以进行输出,结合样例即在窗口到达4 3 8的时候才会进行输出。
(3)我们的窗口在向前滑动,很可能队头却一直停留,因此,必须保证队头在窗口当中。
5. 具体的代码。
//求最小值 for (int i = 0; i < n; i ++) { // 防止溢出 if (tt >= hh && (i - k) >= q[hh]) hh ++; while (tt >= hh && e[q[tt]] >= e[i]) tt --; q[++ tt] = i; if (i - k + 1 >= 0) printf("%d ", e[q[hh]]); }
6. 要寻找最大的元素时,同理,请稍微进行思考一些。
标签:窗口,队列,tt,元素,hh,最小值,滑动 From: https://www.cnblogs.com/481zch/p/17528373.html