当青训营遇上码上掘金
一、题目描述
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)。
输入输出样例:
示例 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;
}
};