当青训营遇上码上掘金-攒青豆

72 阅读2分钟

当青训营遇上码上掘金

一、题目描述

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

image.png

输入输出样例:

示例 1:

输入:height = [5,0,2,1,4,0,1,0,3]

输出:17

解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。

示例 2:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]

输出:6

示例 3:

输入:height = [4,2,0,3,2,5]

输出:9


二、解题过程

1.题目相关

该题的题目原型为接雨水,如42. 接雨水 - 力扣(Leetcode)所示。

可知某个位置上可攒的青豆数取决于它左右两端的柱子的最大高度,同时由于柱子攒豆原理,它攒到的豆子数主要取决于左右最低的那一端,可以使用min(listl[i],listr[i])来表示,而最低端的高度减去当前的高度即为该位置上的青豆数。如果最低端的高度比该位置要小,则攒青豆数为0,可以使用max(0,min(listl[i],listr[i])-height[i])来表示。

所以可将问题转化为求左右两端柱子的最大高度,使用两个循环分别从最左和最右两个位置向相反方向遍历即可。

以示例2的输入height = [0,1,0,2,1,0,1,3,2,1,2,1]为例,遍历得到listl = [0,0,1,1,2,2,2,2,3,3,3,3],listr = [3,3,3,3,3,3,3,2,2,2,1,0],list = [0,0,1,0,1,2,1,0,0,1,0,0],可以接 6 个单位的青豆。

2.参考程序

代码如下(示例):

class Solution {
public:
    int trap(vector<int>& height) {
        int sum=0;
        int Rmax=0;
        int Lmax=0;
        vector<int> listl(height.size());
        vector<int> listr(height.size());
        for(int i=1;i<=height.size()-1;i++){
            listl[i]=height[i-1]>=Lmax?height[i-1]:Lmax;
            Lmax=height[i-1]>=Lmax?height[i-1]:Lmax;
        }
        for(int j=height.size()-2;j>=0;j--){
            listr[j]=height[j+1]>=Rmax?height[j+1]:Rmax;
            Rmax=height[j+1]>=Rmax?height[j+1]:Rmax;
        }
        vector<int> list(height.size());
        for(int i=0;i<=height.size()-1;i++){
            list[i]=max(0,min(listl[i],listr[i])-height[i]);
            sum+=list[i];
        }
         return sum;
    }
};