单调栈定义
从名字上就听的出来,单调栈中存放的数据应该是有序的,所以单调栈也分为单调递增栈和单调递减栈
单调递增栈:单调递增栈就是从栈底到栈顶数据是从大到小
单调递减栈:单调递减栈就是从栈底到栈顶数据是从小到大
参考:[数据结构]——单调栈_lucky52529的博客-CSDN博客_单调递增栈
定义简例
假如有一个单调栈(单调递增)现有以下数字:7,3,5,6,10
- 7入栈时(栈空),7入栈,栈内:7
- 3入栈时(3比7小),3入栈,栈内:7,3
- 5入栈时(5比3大,比7小),3弹栈,5入栈,栈内:7,5
- 6入栈时(6比5大,比7小),5弹栈,6入栈,栈内:7,6
- 10入栈时(10比6大,比7大),6弹栈,7弹栈,栈内:10
伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| 定义数组或者栈; for (遍历原始数据数组){ if (栈空 栈顶元素大于等于当前比较元素){ 入栈; } else{ while (栈不为空 && 栈顶元素小于当前元素){ 栈顶元素出栈; 更新结果; } 当前数据入栈; } }
|
应用
题目
- 小Q在周末的时候和他的小伙伴来到大城市逛街,一条步行街上有很多高楼,共有n座高楼排成一行。小Q从第一栋一直走到了最后一栋,小Q从来都没有见到这么多的楼,所以他想知道他在每栋楼的位置处能看到多少栋楼呢?(当前面的楼的高度大于等于后面的楼时,后面的楼将被挡住)
输入样例
输出样例
样例说明
- 当小Q处于位置3时,他可以向前看到位置2,1处的楼,向后看到位置4,6处的楼,加上第3栋楼,共可看到5栋楼。当小Q处于位置4时,他可以向前看到位置3处的楼,向后看到位置5,6处的楼,加上第4栋楼,共可看到4栋楼。
函数代码(利用动态数组ArrayList模拟栈)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public static int[] findBuilding(int[] heights) { int[] number = new int[heights.length]; ArrayList < Integer > LTR = new ArrayList < Integer > (); ArrayList < Integer > RTL = new ArrayList < Integer > (); for (int i = 0, j = number.length - 1; i < number.length; i++, j--) { number[i] += LTR.size(); number[j] += RTL.size(); while (LTR.size() > 0 && heights[i] > (int) LTR.get(LTR.size() - 1)) { LTR.remove(LTR.size() - 1); } while (RTL.size() > 0 && heights[j] > (int) RTL.get(RTL.size() - 1)) { RTL.remove(RTL.size() - 1); } LTR.add(heights[i]); RTL.add(heights[j]); } for (int i = 0; i < number.length; i++) { number[i] ++; } return number; }
|
更换栈类型函数代码为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public static int[] findBuilding(int[] heights) { int[] number = new int[heights.length]; Stack < Integer > LTR = new Stack < > (); Stack < Integer > RTL = new Stack < > (); for (int i = 0, j = number.length - 1; i < number.length; i++, j--) { number[i] += LTR.size(); number[j] += RTL.size(); while (!LTR.isEmpty() && heights[i] > LTR.peek()) { LTR.pop(); } while (!RTL.isEmpty() && heights[j] > RTL.peek()) { RTL.pop(); } LTR.push(heights[i]); RTL.push(heights[j]); } for (int i = 0; i < number.length; i++) { number[i] ++; } return number; }
|
灵感来源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include <stdio.h>
int main() { int i,n,j, x[100001],LtoR[100001],RtoL[100001],sum[100001]; scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&x[i]); int indl=0,indr=0; for(i=0,j=n-1;i<n,j>=0;i++,j--){ sum[i]+=indl; sum[n-i-1]+=indr; while(LtoR[indl-1]<=x[i]&&indl>0){ indl --; } while(RtoL[indr-1]<=x[j]&&indr>0){ indr --; } LtoR[indl]=x[i]; indl ++; RtoL[indr]=x[j]; indr ++; } for(i=0;i<n-1;i++){ printf("%d ",sum[i]+1); } printf("%d\n",sum[n-1]+1); return 0; }
|
逛街【 腾讯2020校园招聘-后台&综合-第一次笔试】(单调栈的应用)_Twinkle_sone的博客-CSDN博客