当青训营遇上码上掘金
序言
本文记录和整理了本人在字节青训营中学习的一些所得所想,用于本人回顾和梳理相关知识点,也欢迎大家参考,一同学习。如果发现有问题或者错误,可以在下方留言或者私信我(^-^)
题目
主题 4:攒青豆
现有 个宽度为 的柱子,给出 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
示例
以下为上图例子的解析:
-
输入:height = [5,0,2,1,4,0,1,0,3]
-
输出:17
-
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 单位的青豆。
思路
最容易想到的思路就是找到每个位置的最大青豆数量,然后累加。
想要接住青豆,那么其几何形状应该是凹下去的,每个位置的最大青豆数量依赖于其左侧 和右侧的高度, 表示当前位置左侧的最大高度, 表示当前位置右侧的最大高度, 和都可以通过一次遍历来获取。但遍历方向不同, 通过正序遍历, 通过反向遍历。
知道 和后,就可以很轻松的求出当前位置的能接住的最大青豆数量。
复杂度分析
-
时间复杂度:,为数组的长度,总共需要3次遍历。
-
空间复杂度:,为数组的长度,需要创建两个长度为 n+2 的辅助数组 和
代码
码上掘金链接:code.juejin.cn/pen/7198342…
public class Main {
public static void main(String []args) {
System.out.println("Hello world!");
int[] height = {5,0,2,1,4,0,1,0,3};
Main main = new Main();
int res = main.trap(height);
System.out.println(res);
}
public int trap(int[] height) {
int res = 0, n = height.length;
int[] lmax = new int[n + 2];
int[] rmax = new int[n + 2];
// 记录左侧最高点
// lmax[i] == max {h[0] ~ h[i-1]}
lmax[0] = 0;
for(int i = 1; i < n; i ++) {
lmax[i] = Math.max(lmax[i - 1], height[i - 1]);
}
// 记录右侧最高点
// lmax[i] == max {h[i+1] ~ h[len-1]}
rmax[n-1] = 0;
for(int i = n - 2; i >= 0; i --) {
rmax[i] = Math.max(rmax[i + 1], height[i + 1]);
}
for (int i = 0; i < n; i++) {
res += Math.max(Math.min(lmax[i], rmax[i]) - height[i], 0);
}
return res;
}
}