当青训营遇上码上掘金

1,409 阅读2分钟

当青训营遇上码上掘金


主题 4:攒青豆

题目如下:


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

725ef710a59944d49d0315bece7a1ac1_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.webp


解:

  1. 我们观察条件 青豆会尽可能被放入到其中我们反向考虑什么时候青豆会溢出

  2. 青豆无非从左侧或者右侧溢出 且溢出一定是高度高于其中一边高度 所以对于每一个位置上 我们在这个位置上得到青豆的最大高度应该是恰好两边能够找到的最大值中的最小值

    也就是 : min(h_left[i] , h_right[i]) - t[i]

  3. 所以我们需要做的就是横向的从左到右扫描一次得到每一个点左侧的最大值以及从右向左的扫描一次获得右侧的最大值 之后两个最大值取一个min 之后减去我们的基础高度 得到的就是能够攒下来的青豆数量

本题目类似leetcode上的另一道题目leetcode.cn/problems/co… 成水最多的容器 换一种角度思考 那道题是考察的找到两条木棒确定答案 而本题目是考虑所有木棒的情况写应该选取的答案

代码如下: 主题 4:攒青豆 - 码上掘金 (juejin.cn)


    /*** 
     * @Author:       LJY
     * @E-Mail:       575500603@qq.com
     * @ʕ•ﻌ•ʔ :       海压竹枝低复举,风吹山角晦还明
     * @: ------------------------------------------------------
     * @Date: 2023-01-12 21:42:19
     * @LastEditors: TTaket 575500603@qq.com
     * @LastEditTime: 2023-01-12 21:50:30
     */
    #include <bits/stdc++.h>
    using namespace std;


    int get_num(int n , vector<int>t){
        int h_left[n+5] ={} , h_right[n+5] ={};//每一个点左右两侧的最大值
        int hlmax = 0 ,hrmax = 0;
        int ans = 0;

        for(int i = 1;i<=n;i++){
            hlmax = max(hlmax , t[i]);
            h_left[i] = hlmax;
        }
        for(int i = n;i>=1;i--){
            hrmax = max(hrmax , t[i]);
            h_right[i] = hrmax;
        }

        for(int i= 1;i<=n;i++) ans += min(h_left[i] , h_right[i]) - t[i];
        return ans;
    }

    int main(){
        int n , tmpnum;
        vector<int>t(1,0);

        while(cin >> tmpnum) t.push_back(tmpnum);
        int ans = get_num(t.size()-1 , t);
        cout << ans <<endl;

        return 0;
}


码风略丑 读者见谅 2023/1/12