当青训营遇上码上掘金
主题 4:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
观察可知,每个柱子假如是连续递减的话就会形成一个坑,坑的高度由左右两根柱子中较矮的那根决定,坑的宽度=右边柱子下标-左边柱子下标-1,我们可以通过维护一个栈,从而计算出每个坑中的青豆数目。
注意:如果没有柱子的话就直接跳过,处于坑里的柱子计算时需要减去。
代码分析:创建一个栈,遍历数组,如果栈为空就直接入栈;如果栈不为空,判断需要入栈的元素是否比栈顶元素小,如果不是,说明不满足递减,此时就要计算栈中柱子总长度(不包括左边墙那一根),然后在计算坑的高度,宽度,乘起来再减去柱子总长度。最后累加每个坑的青豆总数目。
#include<bits/stdc++.h>
using namespace std;
int height[1010];
int main(void){
int n;
cin>>n;
for(int i=0;i<n;i++){
scanf("%d",&height[i]);
}
stack<int> st;
int ans=0;
int pos=0; // 记录左侧墙的位置
int front=-1; //记录栈顶元素大小
for(int i=0;i<n;i++){
if(height[i]==0){
continue;
}
if(!st.empty()){
front=st.top();
}
if(front!=-1&&front<=height[i]){
int res=0;
while(st.size()!=1){
res+=st.top();
st.pop();
}
int h=min(st.top(),height[i]);
st.pop();
ans+=h*(i-pos-1)-res;
st.push(height[i]);
pos=i;
}else{
st.push(height[i]);
}
}
cout<<ans;
return 0;
}
// 9
// 5 0 2 1 4 0 1 0 3