给定 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 := 0leftMax := 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}
