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

    /**
    * 题目:
    * 给定一个不含重复值的数组arr,找到每一个i位置左边和右边离i位置最近且值比arr[i]小的位置。
    * 返回所有的位置信息。
    * 举例:
    * arr = [3,4,1,5,6,2,7]
    * 返回如下的二维数组作为结果:
    * {
    * {-1 , 2},
    * { 0 , 2},
    * {-1 ,-1},
    * { 2 , 5},
    * { 3 , 5},
    * { 2 ,-1},
    * { 5 ,-1}
    * }
    * -1表示不存在。所以上面的结果表示在arr中,0位置左边和右边离0位置最近且值比arr[0]小的位置
    * 是-1和2;1位置左边和右边离1位置最近且值比arr[1]小的位置是0和2......
    * 要求:
    * 如果arr的长度为N,时间复杂度达到O(N)。
    * 分析:
    * 要使得生成所有的位置信息的同时做到时间复杂度为O(N),这需要用到单调栈的结构。
    * 准备一个栈,记为stack<Integer>,栈中放的元素是数组的位置,开始时stack为空。如果找到每
    * 一个i位置左边和右边离i位置最近且值比arr[i]小的位置,那么需要让stack从栈顶到栈底的位置所代表的值
    * 是严格递减的。(从栈顶到栈底从大到小排列,离当前位置左边最近且比当前位置元素小的就下该位置下面的元素)
    * 例析:
    * 初始arr=[3,4,1,5,6,2,7],stack从栈顶到栈底为:{}
    * 位置角标 0,1,2,3,4,5,6
    * 1.遍历到arr[0]==3时,发现stack为空,就直接放入0位置。stack从栈顶到栈底为{0位置(3)};
    * 2.遍历到arr[1]==4时,由于当前栈顶所对应的值为3,由于arr[1]>3,直接放入1位置不会破坏栈顶到栈底的
    * 位置严格递减的条件,那么将1位置压入栈内,此时stack从栈顶到栈底为{1位置(4),0位置(3)};
    * 3.遍历到arr[2]==1时,发现直接放入2位置会破坏stack从栈顶到栈底的位置所代表的值是严格递减的规律,所以
    * 从stack开始弹出位置。如果x位置被弹出,在栈中位于x位置下面的位置,就是x位置左边离x位置最近且值比arr[x]
    * 小的位置,当前遍历到的位置就是x位置右边离x位置最近且值比arr[x]小的位置。从stack中弹出位置1,在栈中位
    * 于1位置下面的是位置0,当前遍历到的是位置2,所以ans[1]={0,2}。弹出位置1后发现放入位置2还是会破坏stack
    * 从栈顶到栈底的位置所代表的值是严格递减的规律,所以继续弹出位置0。在栈中位于位置0已经没有位置了,说明位置0左边
    * 不存在比arr[0]小的值,当前遍历到的是位置2,所以ans[0]={-1,2}。此时stack已经为空,所以放入2位置(1),
    * 此时stack从栈顶到栈底为{2位置(1)};
    * 4.遍历到arr[3]==5,发现直接放入3位置不会破坏stack栈顶到栈底从大到小的元素排列规律,所以将3位置直接存入
    * 栈内,此时stack从栈顶到栈底为{3位置(5),2位置(1)};
    * 5.遍历到arr[4]==6,发现直接放入4位置不会破坏stack栈顶到栈底从大到小的元素排列规律,所以将4位置直接存入
    * 栈内,此时stack从栈顶到栈底为{4位置(6),3位置(5),2位置(1)};
    * 6.遍历到arr[5]==2,发现直接放入5位置会破坏stack栈顶到栈底从大到小的元素排列规律,因此将4位置弹出stack,
    * 由于当前位置是5,弹出元素位置为4,栈中4位置元素下面位置是3,所以有ans[4]={3,5}。此时stack从栈顶到栈底
    * 为{3位置(5),2位置(1)}。由于arr[5]==2,发现直接放入5位置依然会破坏stack栈顶到栈底从大到小的元素排列规
    * 律,因此将3位置弹出stack,由于当前位置是5,弹出元素位置为3,栈中3位置元素下面位置是2,所以有ans[3]={2,5}。
    * 此时stack从栈顶到栈底为{2位置(1)}。由于arr[5]==2,发现直接放入5位置不会破坏stack栈顶到栈底从大到小的元素
    * 排列规律,因此将5位置存放到stack中,此时stack从栈顶到栈底为{5位置(2),2位置(1)}。
    * 7.遍历到arr[6]==7,发现直接放入6位置不会破坏stack栈顶到栈底从大到小的元素排列规律,所以将6位置直接存入
    * 栈内,此时stack从栈顶到栈底为{6位置(7),5位置(2),2位置(1)}。
    * *******遍历结束******
    * 遍历阶段结束后,清算栈中剩下的位置。
    * 8.弹出6位置,栈中它下面元素是位置5,6位置是清算阶段弹出的所以6位置左边离该位置最近且元素比6位置所对应的元素小的
    * 位置是5位置,6位置右边没有比6位置元素小的位置,所以记为-1,因此ans[6]={5,-1}。此时栈stack从栈顶到栈底为
    * {5位置(2),2位置(1)}。
    * 9.弹出5位置,栈中它下面元素是位置2,5位置是清算阶段弹出的所以5位置左边离该位置最近且元素比5位置所对应的元素小的
    * 位置是2位置,5位置右边没有比5位置元素小的位置,所以记为-1,因此ans[5]={2,-1}。此时栈stack从栈顶到栈底为
    * {2位置(1)}。
    * 10.弹出2位置,此时stack栈为空,由于2位置是清算阶段弹出的,所以ans[2]={-1,-1}。
    *
    * 在整个流程中,由于每个位置都只进栈一次出栈一次,所以时间复杂度是O(N)。
    *
    * @author 雪瞳
    *
    */

    *代码

    import java.util.Stack;
    
    public class getNearLessNoRepeat {
    
        public int[][]getNearElement(int arr[]){
            //由于根据每个位置获取左右的最近值,所以二维数组ans共有arr.length行,两列。
            int ans[][] = new int[arr.length][2];
            Stack<Integer> stack = new Stack<>();
            int count = 0;
            int popIndex=0;
            int leftIndex =0; 
            //遍历阶段
            for(int i=0;i<arr.length;i++) {
                count =arr[i];
                while(!stack.isEmpty() && arr[stack.peek()]>count) {
                    popIndex = stack.pop();
                    if(stack.isEmpty()) {
                        leftIndex = -1;
                    }else {
                        leftIndex = stack.peek();
                    }
                    ans[popIndex][0]=leftIndex;//
                    ans[popIndex][1]=i;//
                }
                stack.push(i);
            }
            //清算阶段
            while(!stack.isEmpty()) {
                popIndex=stack.pop();
                if(!stack.isEmpty()) {
                    leftIndex = stack.peek();
                }else {
                    leftIndex = -1;
                }
                ans[popIndex][0]=leftIndex;
                ans[popIndex][1]=-1;    
            }    
            return ans;
        }
        //显示
        public void showArray(int array[][]) {
            for(int i=0;i<array.length;i++) {
                for(int j=0;j<array[i].length;j++) {
                    System.out.print(array[i][j]+"	");
                }
                System.out.println();
            }
        }
        
    }
    import java.util.Scanner;
    
    public class testGetNearIndex {
        
        public static void main(String[] args) {
            getNearLessNoRepeat test = new getNearLessNoRepeat();
            int N;
            Scanner sc = new Scanner(System.in);
            System.out.println("please input the number!");
            N = sc.nextInt();
            int arr[]=new int[N];
            System.out.println("please input the array elements!");
            for(int i=0;i<N;i++) {
                arr[i]=sc.nextInt();
            }
            int res[][]=new int[arr.length][2];
            res = test.getNearElement(arr);
            test.showArray(res);
        }
        
    }
  • 相关阅读:
    SINAMICS S120/S120 EPOS 基本定位修改方向
    西门子 SINAMICS S120 Web server 用户名和默认密码
    在windows bat脚本(batch)中延时
    ubuntu修改字体大小
    python从字符串中提取数字,使用正则表达式
    python读入文档中的一行
    C++控制台暂停
    在ubuntu linux下安装*.sh的方法
    anaconda和jupyter notebook使用方法
    word禁止自动编号
  • 原文地址:https://www.cnblogs.com/walxt/p/12448238.html
Copyright © 2011-2022 走看看