青训营x码上掘金
主题4:攒青豆
一、问题描述
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
二、解题思路
首先将最左端和最右端设置为两端最大高度,然后从左端第二个和右端第二个位置开始往中间遍历,直到相遇为止。 在遍历数组过程中优先处理最大高度小的一端,然后比较当前端此时的最大高度值和此时遍历到的高度值,如果小于等于最大高度值,则将差值累加到结果中;若大于高度值,则更新当前端最大高度。最后将结果返回即为攒的青豆数量。该算法遍历了一遍数组并且用到了5个变量,所以时间复杂度为O(N),空间复杂度为O(1)。
三、代码
public class Main {
public static void main(String[] args) {
int height[] = {5,0,2,1,4,0,1,0,3};
System.out.println(zanQingDou(height));
}
private static int zanQingDou(int[] nums) {
int leftMax = nums[0]; // 左边当前最大高度
int rightMax = nums[nums.length - 1]; // 右端当前最大高度
int L = 1; // 从左到右遍历到的位置
int R = nums.length - 2; // 从右到左遍历到的位置
int res = 0;
while(L <= R){
// 优先处理当前最大高度小的一端
if(leftMax <= rightMax){
res += Math.max(leftMax - nums[L], 0); // 累加青豆数量
leftMax = Math.max(leftMax, nums[L]); // 更新左端最大高度
++L;
}else{
res += Math.max(rightMax - nums[R], 0); // 累加青豆数量
rightMax = Math.max(rightMax, nums[R]); // 更新右端端最大高度
--R;
}
}
return res;
}
}