当青训营遇上马上掘金!
题目描述
现有 个宽度为 的柱子,给出 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
样例
输入:
输出:
解释:
可见上方图片展示,最多可以盛放 单位的青豆。
题目解答
题目原型
实际上本题目在LeetCode上可以看到类似题目——接雨水,原题是接水,本题是接青豆。
思路求解
我们可以把两个高度中间的地方,看作一个桶,一个桶能不能装青豆,能装多少青豆,取决于这个地方左右两侧的高度的较小者,以及这个地方的高度,两者的差值就是能装青豆的数量。为了获得这三个元素,由于每个地方的高度我们已经知道,我们可以前缀后缀取得最大值,然后两者之间的较小的那个,就是我们的边界,然后减去当前高度即可。
复杂度分析
我们需要分别要求前缀最大值、后缀最大值、接青豆数量,需要遍历数组三次,因此时间复杂度为 。
我们需要前缀、后缀数组来存储最大值,因此空间复杂度是 。
代码实现
public class Main {
public static void main(String[] args) {
int[] heights = {5, 0, 2, 1, 4, 0, 1, 0, 3};
System.out.println(trap(heights));
}
public static int trap(int[] height) {
int n = height.length;
int res = 0;
int[] preMax = new int[n], sufMax = new int[n];
preMax[0] = height[0];
sufMax[n - 1] = height[n - 1];
for (int i = 1; i < n; i++) preMax[i] = Math.max(preMax[i - 1], height[i]);
for (int i = n - 2; i >= 0; i--) sufMax[i] = Math.max(sufMax[i + 1], height[i]);
for (int i = 0; i < n; i++) res += (Math.min(preMax[i], sufMax[i]) - height[i]);
return res;
}
}