给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
c plus
- 按列求(暴力法)
题解
- 按列求,是求本列上面能放多少水,这个和左边最大高度,右边最大高度的较小值有关。即本列存水=较小值-本列的值
注意 int max_left = 0; int max_right = 0;定义在for循环里面,每一列都要求左最大和右最大。粗心定义在外面则会出错。
//直接按问题描述进行。对于数组中的每个元素,我们找出下雨后水能达到的最高位置,等于两边最大高度的较小值减去当前高度的值
class Solution {
public:
int trap(vector<int>& height) {
int length = height.size();
if (length <= 1) return 0;
int sum = 0;
for (int i = 1; i < length- 1; i++) {
int max_left = 0;
int max_right = 0;
for (int j = i - 1; j >= 0; j--) { //求左边最大
if (height[j] > max_left) {
max_left = height[j];
}
}
for (int j = i + 1; j < length; j++) { //求右边最大
if (height[j] > max_right) {
max_right = height[j];
}
}
int min_height = min(max_left, max_right);
if (min_height > height[i]) {
sum += min_height - height[i];
}
}
return sum;
}
};
- 动态规划
- 优化上面解法找左边最大高度和右边最大高度的过程。
- 先把每列的左最大和右最大找出来,存到数组里面去:
- 当前列的左边界最大值,肯定是前一列的左边界最大值和前一列的值中的较大者。
maxLeft[i] 存储中间态,以中间态去推导其他的中间态,也就是DP 方程
也就是当前列的左边界最大值,肯定是前一列的左边界最大值和前一列的值中的较大者。
maxLeft[i] = max(maxLeft[i - 1], height[i - 1]);
class Solution {
public:
int trap(vector<int>& height) {
int sum = 0;
int len = height.size();
vector<int>maxLeft(len, 0);
vector<int>maxRight(len, 0);
for (int i = 1; i < len - 1; i++) { //最后一列是存不到水的,所以不用求
maxLeft[i] = max(maxLeft[i - 1], height[i - 1]);//左边最大从左边开始找
}
for (int i = len - 2; i >= 0; i--) {
maxRight[i] = max(maxRight[i + 1], height[i + 1]);//右边最大从右边开始找
}
for (int i = 1; i < len - 1; i++) {
int m = min(maxLeft[i], maxRight[i]);
if (m > height[i]) {
sum += (m - height[i]);
}
}
return sum;
}
};
func trap(height []int) int {
length := len(height)
if length <= 2 {
return 0
}
sum := 0
leftMax := make([]int, length)
rightMax := make([]int, length)
for i := 1; i < length - 1; i++ {
leftMax[i] = max(leftMax[i - 1], height[i - 1])
}
for i := length - 2; i >= 0; i-- {
rightMax[i] = max(rightMax[i + 1], height[i + 1])
}
for i := 1; i < length - 1; i++ {
minHeight := min(leftMax[i], rightMax[i])
if minHeight > height[i] {
sum += minHeight - height[i]
}
}
return sum
}
func min(a int, b int) int {
if a <= b {
return a
}
return b
}
func max(a int, b int) int {
if a <= b {
return b
}
return a
}