难度:困难

    题目描述:
    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。image.png

    示例:

    1. 输入: [0,1,0,2,1,0,1,3,2,1,2,1]
    2. 输出: 6

    解题思路:
    暴力法:循环遍历元素,每个元素的接水量相当于两边最大高度的较小值减去当前元素高度

    1. var trap = function(height) {
    2. let total = 0;
    3. height.forEach((item, index) => {
    4. let leftMax = 0, rightMax = 0;
    5. for (var i = 0; i <= index; i++) {
    6. leftMax = Math.max(height[i], leftMax);
    7. }
    8. for (var i = index; i < height.length; i++) {
    9. rightMax = Math.max(height[i], rightMax);
    10. }
    11. total += Math.min(leftMax, rightMax) - item
    12. })
    13. return total;
    14. };

    动态编程:用数组记录从左向右和从右向左的最大可能储水量。

    1. var trap = function(height) {
    2. const size = height.length;
    3. let total = 0;
    4. let leftArr = [height[0]];
    5. let rightArr = [height[size - 1]];
    6. for (var i = 1; i < size; i++) {
    7. leftArr.push(Math.max(height[i], leftArr[i-1]));
    8. rightArr.push(Math.max(height[size-1-i], rightArr[i-1]));
    9. }
    10. for (var i = 0; i < size; i++) {
    11. total += Math.min(leftArr[i], rightArr[size-1-i]) - height[i];
    12. }
    13. return total;
    14. };

    如果一侧高度高,则遍历则相对相反的反向比较。比如左侧最大高度小于右侧最大高度,若当前左指针高度小于左侧最大高度,则total加上左侧最大高度-当前左指针高度,否则将最大高度更新为当前左指针高度。

    1. var trap = function(height) {
    2. let left = 0, right = height.length - 1, left_max = 0, right_max = 0, total = 0;
    3. while (left < right) {
    4. if (height[left] < height[right]) {
    5. height[left] < left_max ? total += left_max - height[left] : left_max = height[left];
    6. left++;
    7. } else {
    8. height[right] < right_max ? total += right_max - height[right] : right_max = height[right];
    9. right--;
    10. }
    11. }
    12. return total;
    13. };