第八章(三)滑动窗口

其实滑动窗口类似队列一样,对一些数组区间挺好用的

滑动窗口

输入一个长度为n的序列,寻找尽量长的子序列,使得该子序列中没有相同的元素

思路:每次进来一个a[R],窗口拉伸用map记录出现的元素的下标,如果a[R]的已经出现过并且上次出现的下标值位于[L,R]区间,判断当前子序列[L,R-1]的长度是否更新,再更新L为a[R]上次出现过的下标值+1,这时子序列的区间为[L,R]。如果a[R]并没有出现过,将a[R]放入map中,并更新[L,R]这一段为新的子序列。

 1 /**
 2      * 输入一个长度为n的序列,寻找尽量长的子序列,使得该子序列中没有相同的元素
 3      */
 4     public static void getMin(int[] a) {
 5         int L=0,maxL=0,maxR=0;
 6         HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
 7         for(int R=0;R<a.length;R++) {
 8             if(map.get(a[R])==null||map.get(a[R])<L) {
 9                 map.put(a[R], R);
10                 if(R-L>maxR-maxL) {//[L,R]
11                     maxR=R;maxL=L;
12                 }
13             }else {//碰到相同的了[L,R-1]->[上次出现的位置+1,R]
14                 if(R-L-1>maxR-maxL) {
15                     maxR=R-1;maxL=L;
16                 }
17                 L=map.get(a[R])+1;
18             }
19         }
20         System.out.println("L:"+maxL+" R:"+maxR+" length:"+(maxR-maxL+1));
21     }
22     public static void main(String[] args) {
23         int[]a= {3,4,5,1,2,4,5,3,6};
24         getMin(a);
25     }

滑动窗口+数据结构

滑动窗口的最小值问题:输入正整数k和一个长度为n的整数序列,f(i)表示从元素i开始连续k个元素的最小值,计算出0-(n-k)的最小值

思路:数据结构+滑动窗口,每一个新的元素进来如果他比之前的某些元素小,那么这些元素就不可能再成为最小值。如果他是最大的那么也要插入,因为随着区间的缩短,最小的被输出了那么很有可能会成为最小的。单调队列的话,最小值永远是队头,关键问题是如何知道这个最小值是在这个区间的那个位置,即什么时候更新队头,试想一下,这个最小值如果已经达到区间的边缘那么他们两个应该相等,这个时候应该移动队头,因为如果一个区间内的最小值重复出现,那么在插入的时候就要注意插入多次即可。

 1 /**
 2      * 滑动窗口的最小值问题:输入正整数k和一个长度为n的整数序列
 3      * f(i)表示从元素i开始连续k个元素的最小值,计算出0-(n-k)
 4      * 单调队列来实现
 5      */
 6     public static void getMin(int[] a,int k) {
 7         int[]s=new int[10];
 8         int rear=0;
 9         for(int i=0;i<k;i++) {
10             while(rear>0&&a[i]<s[rear-1]) {
11                 rear--;
12             }
13             s[rear++]=a[i];
14         }
15         int front=0;
16         for(int i=0;i<a.length-k;i++) {
17             System.out.println("f("+i+")="+s[front]);
18             if(s[front]==a[i]) {
19                 front++;
20             }
21             while(rear>front&&a[k+i]<s[rear-1]) {
22                 rear--;
23             }
24             s[rear++]=a[k+i];
25         }
26         System.out.println("f("+(a.length-k)+")="+s[front++]);
27     }
28     public static void main(String[] args) {
29         int[]a= {6,7,8,9,1,2,3};
30         getMin(a,3);
31     }

 

原文地址:https://www.cnblogs.com/code-fun/p/12596186.html