zoukankan      html  css  js  c++  java
  • 每日一题 为了工作 2020 0308 第六题


    /**
    * 问题: 生成窗口最大值数组
    * 有一个整形数组array和一个大小为w的窗口从数组最左边滑到最右边,窗口每次向右边滑动一个位置。
    * 例如,数组为[4,3,5,4,3,3,6,7],窗口大小为3时:
    * [4 3 5] 4 3 3 6 7 窗口的最大值是5
    * 4 [3 5 4] 3 3 6 7 窗口的最大值是5
    * 4 3 [5 4 3] 3 6 7 窗口的最大值是5
    * 4 3 5 [4 3 3] 6 7 窗口的最大值是4
    * 4 3 5 4 [3 3 6] 7 窗口的最大值是6
    * 4 3 5 4 3 [3 6 7] 窗口的最大值是7
    *
    * 如果数组的长度为n,窗口大小为w,则一定会生成n-w+1个窗口的最大值
    * 要求实现一个函数
    * 1.输入:整形数组array,窗口大小w
    * 2.输出:一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。
    * 3.算法的时间复杂度为O(n)
    * 分析:
    * 本题的关键在于利用双端队列来实现窗口最大值的更新。首先生成双端队列qmax,qmax中存放数组
    * array中的下标。
    * 假设遍历到array[i],qmax的放入规则为:
    * 1.如果qmax为空,直接把下标i放进qmax,放入过程结束。
    * 2.如果qmax不为空,取出当前qmax队尾存放的下标,假设为j。
    * 1.如果array[j]>array[i],直接把下标i放到qmax的队尾,放入过程结束。
    * 2.如果array[j]<=array[i],把j从qmax中弹出,重复qmax的放入规则。
    * 实例:
    * 下标: 0 1 2 3 4 5 6 7
    * 大小: 4 3 5 4 3 3 6 7
    *
    *1.开始时qmax为空,即qmax={}。
    *2.遍历到array[0]=4时:
    *由于qmax为空,则将下标0放入到qmax内,此时qmax={0}。
    *3.遍历到array[1]=3时:
    *由于qmax的尾端下标为0,由array[0]>array[1],则将下标1放入到qmax中,此时qmax={0,1}。
    *4.遍历到array[2]=5时:
    *此时窗口array[0,1,2]出现。由于qmax的末尾下标为1,根据array[1]<array[2],故将下标1从qmax末尾弹出,此时qmax={0}。
    *又有array[0]<array[2],故将下标0从qmax末尾弹出,此时qmax={}。
    *由于qmax为空,则将下标2放入到qmax中,此时qmax={2}。
    *由于窗口为[0,1,2],此时下标2还没有过期,故窗口[0,1,2]的最大值是下标2所对应的array[2]。
    *5.遍历到array[3]=4时:
    *此时窗口[1,2,3]出现,由于qmax的末尾下标为2,根据array[2]>array[3],故将下标3放入到qmax中,此时qmax={2,3}。
    *由于窗口为[1,2,3],此时下标2还没有过期,故窗口[1,2,3]的最大值是下标2所对应的array[2]。
    *6.遍历到array[4]=3时:
    *此时窗口[2,3,4]出现,由于qmax的末尾下标为3,根据array[3]>array[4],故将下标4放入到qmax中,此时qmax={2,3,4}。
    *由于窗口为[2,3,4],此时下标2还没有过期,故窗口[2,3,4]的最大值是下标2所对应的array[2]。
    *7.遍历到array[5]=3时:
    *此时窗口[3,4,5]出现,由于qmax的末尾下标为4,根据array[4]=array[5],故将下标4弹出,此时qmax={2,3}。
    *由于此时qmax的末尾下标为3,且array[3]>array[5],故将下标5放入到qmax中,此时下标为qmax={2,3,5}。
    *由于窗口为[3,4,5],此时下标2已经过期,所以将下标2从qmax的头部弹出,此时qmax={3,5}。故窗口[3,4,5]的最大值是下标3所对应的array[3]。
    *8.遍历到array[6]=6时:
    *此时窗口[4,5,6]出现,由于qmax的末尾下标为5,根据array[5]<array[6],故将下标5弹出,此时qmax={3}。
    *由于qmax的末尾下标为3,根据array[3]<array[6],故将下标3弹出,此时qmax={}为空。
    *由于qmax为空,则将下标6存入qmax中,此时qmax={6}。
    *由于窗口为[4,5,6],此时下标6还没有过期,故窗口[4,5,6]的最大值是下标6所对应的array[6]。
    *9.遍历到array[7]=7时:
    *此时窗口[5,6,7]出现,由于qmax的末尾下标为6,根据array[6]<array[7],故将下标6弹出,此时qmax={},为空。
    *由于qmax为空,则将下标7存入qmax中,此时qmax={7}。
    *由于窗口为[5,6,7],此时下标7还没有过期,故窗口[5,6,7]的最大值是下标7所对应的array[7]。
    *
    *上述过程中,每个下标最多进入qmax一次,出qmax一次,所以遍历过程中进出双端队列的时间复杂度是O(n)。
    *
    * @author DELL
    *
    */

    *代码

    import java.util.LinkedList;
    
    public class getMaxArray {
        public int[] getMaxWindow(int array[],int w) {
            
            if(array==null||w<1||array.length<w) {
                throw new RuntimeException("error!your data is not true");
            }
            LinkedList<Integer> qmax = new LinkedList<>();
            //存放的最大值的数组内元素个数最大为n-w+1
            int res[] = new int[array.length-w+1];
            int index = 0;
            for(int i=0;i<array.length;i++) {
                //qmax不为空,且末尾下标对应的数组值小于当前遍历的值,则弹出下标
                //直到qmax为空,或者是末端下标值大则停止遍历将数据追加到双端链表内
                while(!qmax.isEmpty() && array[qmax.peekLast()]<array[i]) {
                    qmax.pollLast();
                }
                qmax.addLast(i);
                //判断下标是否过期
                if(qmax.peekFirst() ==(i-w)) {
                    qmax.pollFirst();
                }
                if(i>= (w-1)) {
                    res[index++] = array[qmax.peekFirst()];
                }
            }
            return res;
        }
        
    import java.util.Random;
    import java.util.Scanner;
    
    public class testGetMaxArray {
        
        public void showArray(int array[]) {
            for(int i:array) {
                System.out.print(i+"	");
            }
        }
        public static void main(String[] args) {
            getMaxArray test = new getMaxArray();
            testGetMaxArray show = new testGetMaxArray();
            Random rand = new Random();
            Scanner sc = new Scanner(System.in);
            
            int N;
            int w;
            System.out.println("请输入数组长度:");
            N=sc.nextInt();
            System.out.println("请输入窗口宽度:");
            w=sc.nextInt();
            
            int array[]= new int[N];
            int res[] = new int[N-w+1];
            for(int i=0;i<N;i++) {
                array[i]=(rand.nextInt(10)+1);
            }
            System.out.println("结果如下");
            show.showArray(array);
            System.out.println();
            res = test.getMaxWindow(array, w);
            show.showArray(res);
        }
    
    }
  • 相关阅读:
    Azure PowerShell (7) 使用CSV文件批量设置Virtual Machine Endpoint
    Windows Azure Cloud Service (39) 如何将现有Web应用迁移到Azure PaaS平台
    Azure China (7) 使用WebMetrix将Web Site发布至Azure China
    Microsoft Azure News(4) Azure新D系列虚拟机上线
    Windows Azure Cloud Service (38) 微软IaaS与PaaS比较
    Windows Azure Cloud Service (37) 浅谈Cloud Service
    Azure PowerShell (6) 设置单个Virtual Machine Endpoint
    Azure PowerShell (5) 使用Azure PowerShell创建简单的Azure虚拟机和Linux虚拟机
    功能代码(1)---通过Jquery来处理复选框
    案例1.用Ajax实现用户名的校验
  • 原文地址:https://www.cnblogs.com/walxt/p/12442484.html
Copyright © 2011-2022 走看看