主题 4:攒青豆

73 阅读2分钟

当青训营遇上码上掘金

主题 4:攒青豆

现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

image.png 以下为上图例子的解析:

输入: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