每日一题 为了工作 2020 03010 第八题

/**
* 题目: 第七题的进阶问题
* 给定一个可能含重复值的数组arr,找到每一个i位置左边和右边离i位置最近且值比arr[i]小的位置。
* 返回所有的位置信息。
* 分析:
* 初始arr=[3,1,3,4,3,5,3,2,2],stack从栈顶到栈底为:{}
* 位置角标 0,1,2,3,4,5,6,7,8
* 1.遍历到arr[0]==3时,发现stack为空,直接将0位置的角标存入到stack栈内,此时stack从栈顶到栈底的元素依次是{0位置(3)};
*
* 2.遍历到arr[1]==1时,此时stack栈顶的元素是位置0,由于arr[0]>arr[1],若将1位置放入栈内,不满足stack元素从栈顶到栈底
* 元素是依次减小的变化规律,故将0位置弹出stack栈,此时stack为空,即为{},由于弹出的是位置0,栈内为空所以res={-1,1};由于
* stack为空,此时将位置1压入栈内,stack从栈顶到栈底的元素依次是{1位置(1)};
*
* 3.遍历到arr[2]==3时,发现将2位置直接压入栈内不会破坏stack栈从栈顶到栈底元素依次减小的规律,故将2位置压入栈内,此时stack
* 栈从栈顶到栈底的元素依次是{2位置(3),1位置(1)};
*
* 4.遍历到arr[3]==4时,发现将3位置直接压入栈内不会破坏stack栈从栈顶到栈底元素依次减小的规律,故将3位置压入栈内,此时stack
* 栈从栈顶到栈底的元素依次是{3位置(4),2位置(3),1位置(1)};
*
* 5.遍历到arr[4]==3时发现,将4位置直接压入栈内会破坏stack栈从栈顶到栈底元素依次减小的规律,故将3位置弹出栈,由于当前弹出的
* 位置是3位置,3位置再栈内的下一元素位置是2位置,所以res[3]={2,4};此时stack栈从栈顶到栈底的元素依次是{2位置(3),1位置(1)};
* 由于arr[4]==arr[2]==3,即为当前遍历到的位置对应的元素值与stack当前栈顶的元素对应初始数组位置值相同,所以将两个位置压在一起。
* 此时stack栈从栈顶到栈底的元素依次是{[2位置,4位置](3),1位置(1)};
*
* 6.遍历到arr[5]==5时,发现将5位置直接压入栈内不会破坏stack栈从栈顶到栈底元素依次减小的规律,故将5位置压入栈内,此时stack
* 栈从栈顶到栈底的元素依次是{5位置(5),[2位置,4位置](3),1位置(1)};
*
* 7.遍历到arr[6]==3时发现,此时stack栈顶元素是5位置,由于arr[5]>arr[6],故将6位置直接压入栈内会破坏stack栈从栈顶到栈底元
* 素依次减小的规律,故将5位置弹出栈,由于当前弹出的位置是5位置,5位置再栈内的下一元素位置是[2位置,4位置],选择最晚加入的4位置作为
* 比当前元素小且距离最近的位置,即为res[5]={4,6}。此时stack栈从栈顶到栈底的元素依次是{[2位置,4位置](3),1位置(1)};由于此时
* stack的栈顶元素是[2位置,4位置],由于arr[6]==arr[2]==arr[4]==3,即为当前遍历到的位置对应的元素值与stack当前栈顶的元素
* 对应初始数组位置值相同,所以将三个位置继续压在一起。此时stack栈从栈顶到栈底的元素依次是{[2位置,4位置,6位置](3),1位置(1)};
*
* 8.遍历到arr[7]==2时,发现此时stack栈顶元素是[2位置,4位置,6位置],由于arr[7]<arr[6]==arr[2]==arr[4]==3,故将7位置
* 直接压入栈内会破坏stack栈从栈顶到栈底元素依次减小的规律,故将[2位置,4位置,6位置]弹出栈,由于当前弹出的位置是[2位置,4位置,6位置],
* [2位置,4位置,6位置]再栈内的下一元素是位置1,因此res[2]={1,7},res[4]={1,7},res[6]={1,7}.此时stack栈从栈顶到栈底的元
* 素依次是{1位置(1)};此时将7位置压入栈内不会破坏stack栈从栈顶到栈底元素依次减小的规律,故将7位置压入栈内,此时stack栈从栈顶到栈底
* 的元素依次是{7位置(2),1位置(1)};
*
* 9.遍历到arr[8]==2时,此时stack的栈顶元素是位置7,由于arr[8]==arr[7]==2,即为当前遍历到的位置对应的元素值与stack当前栈顶的
* 元素对应初始数组位置值相同,所以将两个位置压在一起。此时stack栈从栈顶到栈底的元素依次是{[7位置,8位置](2),1位置(1)}。
*
* ************遍历结束************
* 10.遍历完成进入清算阶段
*
* ************清算阶段************
* 1.由于stack栈从栈顶到栈底的元素依次是{[7位置,8位置](2),1位置(1)},将栈顶元素弹出栈,即为弹出[7位置,8位置],由于[7位置,8位置]在
* 栈内的下一元素是1位置,同时由于是清算阶段弹出的元素,所以当前弹出元素的右边没有比当前元素小的元素。故res[7]={1,-1},res[8]={1,-1}。
* 此时stack栈从栈顶到栈底的元素依次是{1位置(1)};
* 2.由于stack栈从栈顶到栈底的元素依次是{1位置(1)},从栈内弹出1位置,此时栈stack为空,即为{}。由于1位置是清算阶段弹出的,
* 所以res[1]={-1,-1}。
*
* @author 雪瞳
*
*/

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class getNearLessElements {

    public int[][] getNearElements(int arr[]){
        int length = arr.length;
        int res[][] = new int[length][2];
        int IndexElement = 0;
        int popIndex = 0;
        int leftElement = 0;
        int rightElement = 0;
        //将列表存储于栈内,相同位置元素存储于同一个列表内
        Stack<List<Integer>> stack = new Stack<>();
        for(int i=0;i<length;i++) {
            
            IndexElement = arr[i];
            //栈需要弹出元素
            while(!stack.isEmpty() && arr[stack.peek().get(0)]>IndexElement) {
                
                List<Integer> popList=stack.pop(); 
                
                if(stack.isEmpty()) {
                    leftElement = -1;
                }else {
                    //获取栈顶元素所返回的列表,选取最后加入的那个作为左边的位置
                    List<Integer> tip = stack.peek();
                    leftElement = tip.get(tip.size()-1);
                }
                //遍历弹出的列表
                for(int j=0;j<popList.size();j++) {
                    popIndex = popList.get(j);
                    res[popIndex][0]=leftElement;
                    res[popIndex][1]=i;
                }
            }
            //栈不需要弹出元素
            //当栈顶元素和当前遍历元素所对应的数组值相同
            if(!stack.isEmpty() && arr[stack.peek().get(0)]==IndexElement) {
                //将i转化成Integer类型并存入到栈顶列表内
                stack.peek().add(Integer.valueOf(i));
            }else {
                //不同则直接将当前遍历位置存入列表并压入栈内
                List<Integer> ls = new ArrayList<Integer>();
                ls.add(Integer.valueOf(i));
                stack.push(ls);
            }    
        }
        //清算阶段
        while(!stack.isEmpty()) {
            List<Integer> list = stack.pop();
            //获取leftElement元素
            if(!stack.isEmpty()) {
                List<Integer> ls = stack.peek();
                leftElement = ls.get(ls.size()-1);
            }else {
                leftElement = -1;
            }
            //遍历列表
            for(int i=0;i<list.size();i++) {
                popIndex = list.get(i);
                res[popIndex][0]=leftElement;
                res[popIndex][1]=-1;
            }
        }
        
        return res;
    }
    public void showElements(int array[][]) {
        for(int arr[]:array) {
            for(int element:arr) {
                System.out.print(element+"	");
            }
            System.out.println();
        }
    }
}
import java.util.Random;
import java.util.Scanner;

public class testGetNearElements {
    public static void main(String[] args) {
        getNearLessElements test = new getNearLessElements();
        testGetNearElements show = new testGetNearElements();
        Scanner sc = new Scanner(System.in);
        Random rand = new Random();
        System.out.println("please input the array length");
        int len = sc.nextInt();
        int arr[]=new int[len];
        for(int i=0;i<len;i++) {
            arr[i]=(rand.nextInt(10)+1);
        }    
        show.showArray(arr);
        int res[][]=new int[arr.length][2];
        res = test.getNearElements(arr);
        test.showElements(res);
    }
    public void showArray(int array[]) {
        for(int element :array) {
            System.out.print(element+"	");
        }
        System.out.println();
    }
}
原文地址:https://www.cnblogs.com/walxt/p/12455188.html