在数组中想找到一个数, 左边和右边比这个数小、 且离这个数最近的位置。
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
//单调栈
public class MonotonousStack {
public static void main(String[] args) {
int[] arr = {3,4,2,5,6,0,1};
int[][] darr = MonotonousStack.getNearLessNoRepeat(arr);
MonotonousStack.printArr(darr);
System.out.println("---------------");
int[] arr2 = {3,4,2,5,6,0,1};
darr = MonotonousStack.getNearLess(arr2);
MonotonousStack.printArr(darr);
}
private static void printArr(int[][] darr){
for (int i = 0; i < darr.length; i++) {
for (int j = 0; j < darr[0].length; j++) {
System.out.print(darr[i][j]+" ");
}
System.out.println();
}
}
/**
* 得到每一个位置上,左边距离这个数最近,并且小于当前数的数。
* 右边距离这个数最近,并且小于当前数的数。
*
* @param arr(不包含重复数字)
* @return [i][0]左边, [i][1]右边
*/
public static int[][] getNearLessNoRepeat(int[] arr){
int[][] res = new int[arr.length][2];
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < arr.length; i++) {
while(!stack.isEmpty() && arr[stack.peek()] > arr[i]){
// 栈顶的数据比当前位置的数大,弹出栈顶数
int popIndex = stack.pop();
int leftIndex = stack.isEmpty() ? -1 : stack.peek();
res[popIndex][0] = leftIndex;
res[popIndex][1] = i;
}
stack.push(i);
}
while(!stack.isEmpty()){
int popIndex = stack.pop();
int leftIndex = stack.isEmpty() ? -1 : stack.peek();
res[popIndex][0] = leftIndex;
res[popIndex][1] = -1;
}
return res;
}
/**
* 得到每一个位置上,左边距离这个数最近,并且小于当前数的数。
* 右边距离这个数最近,并且小于当前数的数。
*
* @param arr(包含重复数字)
* @return [i][0]左边, [i][1]右边
*/
public static int[][] getNearLess(int[] arr){
int[][] res = new int[arr.length][2];
// List<Integer>>放的是位置, 同样值的东西,位置压在一起
Stack<List<Integer>> stack = new Stack<>();
for (int i = 0; i < arr.length; i++) {
while(!stack.isEmpty() && arr[stack.peek().get(0)] > arr[i]){
// 底 -> 顶, 小 -> 大
List<Integer> popIs = stack.pop();
// 取位于下面位置的链表中,最晚加入的那个
int leftIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size()-1);
for(Integer popi : popIs){
res[popi][0] = leftIndex;
res[popi][1] = i;
}
}
// 栈顶的值与当前值相等
if(!stack.isEmpty() && arr[stack.peek().get(0)] == arr[i]){
stack.peek().add(Integer.valueOf(i));
}else{
// 将当前值入栈
ArrayList<Integer> list = new ArrayList<>();
list.add(i);
stack.push(list);
}
}
while(!stack.isEmpty()){
List<Integer> popIs = stack.pop();
// 取位于下面位置的链表中,最晚加入的那个
int leftIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size()-1);
for(Integer popi : popIs){
res[popi][0] = leftIndex;
res[popi][1] = -1;
}
}
return res;
}
}