• 第八章(三)滑动窗口


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

    滑动窗口

    输入一个长度为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     }

     

  • 相关阅读:
    [luoguP3953] 逛公园(DP + spfa)
    [luoguP3960] 列队(动态开点线段树)
    [luoguP2325] [SCOI2005]王室联邦(树分块乱搞)
    [luoguP1053] 篝火晚会(贪心 + 乱搞)
    Linux_C socket 一些知识
    Linux_C socket 服务器(cat ,execl功能)
    Linux_C socket server.c clinet.c功能分开写
    Linux_C socket clinet.c
    Linux_C AF_INET和PF_INET的细微不同
    Linux_socket一些基本函数和结构体
  • 原文地址:https://www.cnblogs.com/code-fun/p/12596186.html
Copyright © 2020-2023  润新知