当青训营遇上码上掘金, 青训营主题四攒青豆,题目:
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
分析
根据题目可以得出,和短板效应很像。每个柱子长短不齐,能接住豆子主要是靠左右两边较高的柱子做边形成凹槽。且接住豆子的多少取决于两边中较矮的那个。故可以通过遍历数组,查找能形成凹槽的柱子的两个边,从而计算接住的豆子。 所以我们可以先定义两个变量记录左右两边依次前进进度的值,在定义两个变量来记录左右两端的最大值。两边依次进行比较,如果左右指针指向的值大于对应的最大值,则更新最大值为当前值,小的一边再与其紧邻的值与最大值做差,依次遍历,当左右两个指针为同一位置时,结束循环计算青豆。
代码实现
//双指针法
public class Main {
public static void main(String[] args) {
int[] height = { 5, 0, 2, 1, 4, 0, 1, 0, 3};
int sum = Calculate.calculate(height);
System.out.println(sum);
}
}
class Calculate {
public static int calculate(int[] arr) {
//标记循环左右的值
int Left = 0;
int Right = arr.length - 1;
//标记左右最大值
int MAX_L = 0;
int MAX_R = 0;
int sum = 0;
//哪边小就算哪边变,短板效应
while (Left < Right) {
if (arr[Left] < arr[Right]) {
if (arr[Left] >= MAX_L) {
MAX_L = arr[Left];
}
sum += MAX_L - arr[Left++];
} else {
if (arr[Right] >= MAX_R) {
MAX_R = arr[Right];
}
sum += MAX_R - arr[Right--];
}
}
return sum;
}
}
代码链接码上掘金