题目
一个不含有重复值的数组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长度为N,时间复杂度达到O(N)。
思路
数据结构:单调栈,存放数组元素的索引
使用一个栈,并且使该栈从栈顶到栈底的值是严格递减的(因为找的是左右两边比当前位置小的值)。
流程:
- 遍历数组
- 栈为空或者当前arr[i]大于栈顶元素直接入栈
- 若栈不为空,并且当前arr[i]小于栈顶元素 j(假设为j,因为栈里存放的是数组索引值,这里比较的是arr[i]<arr[j]),则需要弹出栈顶元素,则对于弹出的元素j来说左边位置离j最近并且小于arr[j]的值为当前栈顶对应的值,右边位置则是i;
- 遍历完数组后,若栈不为空,则对于栈中的所有元素,它们的右边位置最近并且小于他们的值都不存在即为-1;依次弹出栈顶元素 j (假设为j),j的右边为-1,左边位置为当前栈顶元素;完成!
源码
public int[][] getNearLessNoRepeat(int[] arr){
//返回的二维数组,代表左右的位置
int[][] res=new int[arr.length][2];
//栈
Stack<Integer> stack=new Stack<Integer>();
//遍历数组
for(int i=0;i<arr.length;i++){
//栈不为空,并且当前数组元素小于栈顶元素
while(!stack.isEmpty()&&arr[stack.peek()]>arr[i]){
int popIndex=stack.pop();
int leftlessIndex=stack.isEmpty()?-1:stack.peek();
int rightlessIndex=i;
//针对于弹出的栈顶元素的左右最小的值的位置
res[popIndex][0]=leftlessIndex;
res[popIndex][1]=rightlessIndex;
}
stack.push(i);
}
while(!stack.isEmpty()){
int popIndex=stack.pop();
int leftlessIndex=stack.isEmpty()?-1:stack.peek();
int rightlessIndex=-1;
res[popIndex][0]=leftlessIndex;
res[popIndex][1]=rightlessIndex;
}
return res;
}
如果有不理解的,欢迎随时留言交流。