每日一题 为了工作 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);
    }
    
}
原文地址:https://www.cnblogs.com/walxt/p/12448238.html