当青训营遇上码上掘金
一、题目原型:
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
输入:height = [5,0,2,1,4,0,1,0,3] 输出:17 解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
二、想法思路
首先看到这个题目第一反应有点膈应,因为我们青训营就是要攒这该死的“青豆”,于是我毫不犹豫的选择了这个题目来“攒青豆”。本题目可以类比为一个不规则容器接雨水的例子,联合实际,只有在两根柱子之间形成“沟壑”才能攒青豆,乍一看只要找到只要依次分别找到形成“沟壑”的一对柱子就能解决问题,实则不然,因为这样会漏掉一些柱子之间形成的“沟壑的空间”,经过一番冥想,发现只要利用贪心算法,只要依次找到当前位置后最高的柱子(局部最高柱子 当然,其位置肯定不能和当前柱子位置相邻,因为这样形成不了“沟壑”),然后计算当前位置柱子和局部最高柱子所能容下的青豆,最后当前位置移动到局部最高柱子的位置,重复上述操作。
三、代码
c++代码
#include <iostream>
#include <vector>
using namespace std;
int Stat(vector<int>v){
size_t size = v.size();
int begin = 0; //当前柱子的起始位置
int sum = 0; //记录总数
int index; //记录局部最高柱子所在的位置
while(size-2>begin){
int m = 0; //记录每一次起始位置后的最大值
//搜索当前位置后局部最高柱子并记录位置
for(int i = begin+2;i<size;++i){
if(v[i]>m){
m=v[i];
index = i;
}
}
//最高柱子高度为0之间退出循环
if(m==0)
break;
//比较当前柱子和局部最高柱子的高度 用作下面的计算容纳青豆的数量
int temp = min(v[begin],m);
for(int j = begin+1;j<index;++j){
if(temp-v[j]>0)
sum+= temp-v[j];
}
//更新当前位置
begin = index;
}
return sum;
}
int main() {
cout<<Stat({5,0,2,1,4,0,1,0,3});
return 0;
}