这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
-
一、题目:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
二、我的解答
想法: 每次遍历的高度的数字可以向两边拓展,遇到比自己大的就接着拓展,小的就停止,然后用自己的高度乘以拓展的宽度,所以我们这里借助单调栈的方法。
我们使用一下单调递增栈。
思路:
1.设置一个单调递增的栈
2.当遇到小于栈顶元素的值,我们开始更新数据
具体做法:
首先,我们先遍历每个柱子的高度,前三个高度入栈,继续遍历,当遇到栈顶元素小于新加入的元素的情况,栈顶元素出栈。
那么,如果我们的栈里面还有存在着元素,我们所需求的单位青豆,即面积,就可以通过“底乘高”来计算。
底的计算:(当前遍历到的i)- (现在栈顶的高度元素)-1
高的计算:将新遍历的元素与当前栈的元素比较,取最小的值,得出h1。然后h1与第一步出栈的元素相减,得出高H。
于是,面积就可以通过(底* 高)的方式得出结果。
当栈顶元素大于新来的元素时,栈里面添加元素。
最终,按照题目要求,我们需要求出,按此排列的柱子能接住多少青豆,所以每次求出的面积的结果要累加起来,得到答案并输出我们的结果。
综上分析:代码如下:
class Solution {
public int trap(int[] height) {
int n = height.length ;
Stack<Integer> s = new Stack<>();
int res = 0 ;
for(int i = 0 ; i < n ; i++){
while(s.size() > 0 && height[s.peek()] <= height[i]){
int t = s.pop();
if(s.size() > 0){
int h = Math.min(height[s.peek()],height[i]);
res += (i - s.peek() - 1 )* (h-height[t]) ;
}
}
s.push(i);
}
return res ;
}
}
三、个人总结
在分析问题的时候,我的思考时间较长,也阅读了有关单调栈的资料,解决问题的过程中,学到了很多新东西。