题目描述来自leetcode
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
代码:
public static int trap(int[] height) {
int sum = 0;
if (height.length == 0) {
return 0;
}
int[] leftMax = new int[height.length];
int[] rightMax = new int[height.length];
//求每一个高度的右边最大的墙
//为什么呢?因为右边的墙是左边能存的最多的水的条件
rightMax[height.length - 1] = height[height.length - 1];
for (int i = height.length - 2; i >= 0; i--) {
rightMax[i] = Math.max(height[i], rightMax[i + 1]);
}
//求每一个高度的左边最大的墙
leftMax[0] = height[0];
for (int i = 1; i < height.length; i++) {
leftMax[i] = Math.max(height[i], leftMax[i - 1]);
}
//遍历每个数组中的每个元素根据左右边的最大墙取当前数组可以存的最多的水
for (int i = 0; i < height.length - 1; i++) {
if (leftMax[i] <= rightMax[i]) {
sum += leftMax[i] - height[i];
} else {
sum += rightMax[i] - height[i];
}
}
return sum;
}
分析:
首先关键点要看出来:求一个节点他能盛多少水取决于他的左边的最高墙和右边的最高墙;
这个算法的思路是对暴力法的优化,暴力法就是对于数组的每一个点判断他的全局的左边的墙和右边的墙的高度,从两者之间选择低的那个,本算法只是先把每个节点的最左最高和最右最高的墙记录下,然后直接用就行,不必每次遍历都去求了
其他方法下一篇更新