青训营码上掘金之主题四:攒青豆

97 阅读2分钟

当青训营遇上码上掘金

一、题目原型:

现有 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 个单位的青豆。

二、想法思路

首先看到这个题目第一反应有点膈应,因为我们青训营就是要攒这该死的“青豆”,于是我毫不犹豫的选择了这个题目来“攒青豆”。本题目可以类比为一个不规则容器接雨水的例子,联合实际,只有在两根柱子之间形成“沟壑”才能攒青豆,乍一看只要找到只要依次分别找到形成“沟壑”的一对柱子就能解决问题,实则不然,因为这样会漏掉一些柱子之间形成的“沟壑的空间”,经过一番冥想,发现只要利用贪心算法,只要依次找到当前位置后最高的柱子(局部最高柱子 当然,其位置肯定不能和当前柱子位置相邻,因为这样形成不了“沟壑”),然后计算当前位置柱子和局部最高柱子所能容下的青豆,最后当前位置移动到局部最高柱子的位置,重复上述操作。

三、代码

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;
}

go代码