当青训营遇上码上掘金
-
主题 4:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
思路:
首先朴素想法就是以每列为中心,会发现除了第一列和最后一列以后,每一列的计算方法都是根据柱子的高度来确定的,如何确定的呢,首先我们观察例子中的第二列我们会发现他的高度取决于右边最高的那个,一直到倒数第二列都是这样的,从中我们可以发现,我们应该找到这一列左右两边最高的中的相对较矮的那一个,然后作为边界条件进行计算,我们使用朴素的算法时间复杂度是n的平方,所以我们可以事先把最值存好,在这里我们就使用了动态规划了,把所有的问题细化成一个小问题,然后在小问题中寻找出最优解,然后找到答案。
代码:
int n = height.length;
int ml[]=new int[n];
int mr[]=new int[n];
ml[0]=height[0];//左边第一个柱子默认为起始
for(int i=1;i<n;i++){
ml[i]=Math.max(height[i],ml[i-1]);//判断当前柱子的左边最高的柱子(包括当前柱子)
}
mr[n-1]=height[n-1];//右边第一个柱子默认为结尾
for(int i=n-2;i>=0;i--){
mr[i]=Math.max(height[i],mr[i+1]);
}
int sum=0;
for(int i=1;i<n-1;i++){
int a=Math.min(mr[i],ml[i])-height[i];
sum+=a;
}
return sum;