这篇博客是基于左程云的程序员代码面试指南的内容来写的
题目要求:
给定一个不含有重复值的数组 arr,找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i]小的位置。返回所有位置相应的信息。
首先想到的肯定是暴力了,从每个数向二边开始去找。这样的复杂度为O(N^2),理解起来也很简单,代码如下展示:
int l = -1;
int r = -1;
for (int i = 0; i < n; i++) {
//先遍历左边
for (int j = i; j >=0 ; j--) {
if (res[j] < res[i]){
l = j;
break;
}
}
for (int j = i; j < n; j++) {
if (res[j] < res[i]){
r = j;
break;
}
}
System.out.println(l + " " + r);
l = -1;
r = -1;
}
就是从它的左右二边去标记下最小值就行,一旦找到就break。
下面介绍下单调栈,时间复杂度0(N),空间复杂度0(N);
单调栈的定义为:整个栈里的值都是一直变小或者一直变大的,不会出现违反这个规则的情况。
先对代码进行展示,在对它进行解释。
Stack<Integer> result = new Stack<>();
for (int i = 0; i < n; i++) {
if (result.isEmpty()){//如果是空的话就把这个数放进去
result.add(i);
}else {
if (res[i] < res[result.peek()]){//如果它小于等于
while (!result.isEmpty() && res[i] < res[result.peek()]){
Integer pop = result.pop();
if (result.isEmpty()){
temp[pop][0] = -1;
}else {
temp[pop][0] = result.peek();
}
temp[pop][1] = i;
}
result.add(i);
}else {
result.add(i);
}
}
}
while (!result.isEmpty()){
Integer pop = result.pop();
if (result.isEmpty()){
temp[pop][1] = -1;
temp[pop][0] = -1;
}else {
temp[pop][1] = -1;
temp[pop][0] = result.peek();
}
}
for (int i = 0; i < n; i++) {
System.out.println(temp[i][0] + " " + temp[i][1]);
}
首先举个栗子:
对于一个数组: 4 2 6 8 1 3 7
1.首先拿出4,发展栈空,把4压入栈;
2.将2与栈顶4比较小于4,所以4的右边比它小的数就是2,左边比它小的是栈中它下面的数,如果不存在则为-1,4弹出后接着比较,发现栈空,2压入栈;
所以4的结果就是 -1 1;
3.6与栈顶元素比较,大于2直接压入栈;
4.8与6比较小于,直接压入栈;
5.1与8比较,小于8,所以8弹出,右边比它小的数就是1,左边比它小的是栈中它下面的数6,8弹出后接着进行比较。所以8的结果就是 2 4 ;
6.1与6比较,小于6,所以6弹出,右边比它小的数就是1,左边比它小的是栈中它下面的数2,6弹出后接着进行比较。所以6的结果就是 1 4 ;
7.1与2比较,小于2,所以6弹出,右边比它小的数就是1,左边比它小的是栈中它下面的数2,6弹出后接着进行比较。所以2的结果就是 -1 4;发现栈空,1压入栈;
8.3与栈顶元素比较,大于1直接压入栈;
9.7与栈顶元素比较,大于3直接压入栈;
10.所有数均压入栈完毕,此时如果栈不为空的话,则依次弹出,右边比它小的数为-1,左边为栈中下面的数组。
所以7的结果就是5 -1;
所以3的结果就是4 -1;
所以1的结果就是-1 -1;
大概流程,如图所示,emm第一次画不太会画。多包涵。
下面对为什么单调栈结构所弹出的数,一定是符合要求的进行解释:
首先解释为什么放入的数字比栈顶数字小就一定是它右边最小的数字:
这里假设这个数字之前有一个数字比栈顶元素小,则这个栈顶元素一定早就弹出栈了,所以一定不会有这个数字到被弹出数字之间比被弹出数字小的数组。
其次解释为什么这个数字下面的数字就是比它小的最左边的第一个数字。
还假设下面的数字到这个数字之间还存在比它小的数字,那么根据上面的规则则这个数字肯定已经被弹出了。所以此时被弹出数字下面的数字一定是这个数字左边第一个比它小的数字。
至此解释完毕。其实这种假设的方法可以用来帮助解决很多这种算法结构的问题,hhh以后自己多体会吧。
单调栈的用法:后面有题目用到在来进行补充!