当青训营遇上码上掘金--主题4 攒青豆。本次趁寒假参加了字节青训营,打算充实一下自己,学习一些知识。营里大佬们很多,大家都很积极努力!!话不多说,我们先来看看这道攒青豆的题目吧!
题目
-
主题 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 个单位的青豆。
分析
首先,观察题目我们可以发现,能接住豆子主要是靠左右两边较高的柱子做‘边’形成“凹槽”。且接住豆子的多少取决于两个‘边’中较矮的那个。故该题我们可以通过遍历数组,查找能形成“凹槽”的柱子的两个‘边’,从而计算接住的豆子。
例如,‘2’柱子,左侧柱子中最高的是‘5’,右侧柱子中最高的是‘4’,形成凹槽。两个边中较矮的那个为‘4’,故该柱子上方能装的青豆为4-2=2个单位的青豆。 '4'柱子左侧最高为'5',右侧没有比它自己更到的柱子了,多以无法形成”凹槽“,接豆子数为0。
需注意,左右两侧的柱子只能当边,无法做底部。故我们计算的柱子只需从1~length-1即可。
代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int solution(vector<int> &height){
//计数
int sum=0;
//两侧柱子只能当边,无法做底部,故循环条件为1~length-1
for(int i=1;i<height.size()-1;i++){
//maxleft表示左侧最高的柱子,初始值设为最左侧柱子 。同理,右侧为maxright
int maxleft=height[0];
int maxright=height[height.size()-1];
//循环左侧查找最大的柱子
for(int j=1;j<i;j++){
if(height[j]>maxleft){
maxleft=height[j];
}
}
//同理,循环右侧查找最高柱子
for(int j=i+1;j<height.size()-1;j++){
if(height[j]>maxright){
maxright=height[j];
}
}
//比较两个‘边’,取最小值
int minmax=min(maxleft,maxright);
//两‘边’需要高于当前柱子才能形成“凹槽”
//接豆子高度即为'边'中较低柱子的高度-当前柱子的高度
if(height[i]<minmax){
sum+=minmax-height[i];
}
}
return sum;
}
int main() {
vector<int> height;
int x;
while(cin >> x){
height.push_back(x);
if (cin.get() == '\n'){
break;
}
}
cout <<solution(height)<<endl;
return 0;
}
当然此种方法最为简单易懂,使用其他算法的方法也还有很多,小伙伴们一起去发现吧~