当我脑子里出现这个轨迹时,单调栈的原理全想明白了
5
3 4
2
1import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] stringsNums = br.readLine().split(" ");
int[] arr = new int[n];
for(int i=0;i<n;i++){
arr[i]=Integer.parseInt(stringsNums[i]);
}
int[][] res = getResult(arr,n);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < n; ++i) {
builder.append(res[i][0]).append(' ').append(res[i][1]).append('\n');
}
System.out.println(builder.toString());
}
//单调栈思想
//第一个元素下标入栈,下一个如果大于栈顶元素则直接入栈,
//下一个如果小于栈顶元素,这时可以得到当前栈顶元素的 左右位置结果信息,
//栈顶元素出栈,继续对比,如果待入栈元素仍然小于栈顶,则得到了当前栈顶的左右位置结果
//栈顶元素继续出栈,直到栈顶元素大于待入栈的元素
//arr入栈完毕后,如果栈中还有元素,则右位置结果一定为-1
//不停出栈,可得到左位置结果信息,
//如此反复,直到出栈完毕,最后一个元素的左位置信息一定为-1
public static int[][] getResult(int[] arr,int size){
// if(size==1) return new int[][]{{-1,-1}};
int[][] result = new int[size][2];
Stack<Integer> stack = new Stack<>();
for(int i=0;i<size;i++){
if(stack.isEmpty()){
stack.push(i);
}else{
while(!stack.isEmpty()){
//大于栈顶元素,直接入栈
if(arr[i]>arr[stack.peek()]){
stack.push(i);
break;
}else{
//得到了栈顶元素的结果信息
int curIndex = stack.pop();
result[curIndex][1]=i ;//右位置
if(stack.isEmpty()){
result[curIndex][0]=-1;//左位置
//栈空了,没必要继续循环了,入栈,退出while
stack.push(i);
break;
}else{
result[curIndex][0]=stack.peek();//左位置
}
}
}
}
}
//处理特殊情况
//1、size=1的情况
//2、最后一个元素小于栈中所有元素
//3、最后一个元素大于栈顶元素
//4、最后一个元素不完全大于栈中所有元素
while(!stack.isEmpty()){
//得到了栈顶元素的结果信息
int curIndex = stack.pop();
result[curIndex][1]=-1 ;//右位置
if(stack.isEmpty()){
result[curIndex][0]=-1;//左位置
}else{
result[curIndex][0]=stack.peek();//左位置
}
}
return result;
}
}
京公网安备 11010502036488号