42.接雨水

2020-04-17
接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,

计算按此排列的柱子,下雨之后能接多少雨水。

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,

在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)

题解:
思路1:记录每一个下标左右最大值
 
var trap = function (height) {
  let leftMax = 0, rightMax = 0;
  let LMArr = [], RMArr = [];
  let sum = 0;
  for (let i = 0; i < height.length; i++) { // 第一个遍历找到height每一项对应的左边的最大值 
    leftMax = Math.max(height[i], leftMax);
    LMArr.push(leftMax); // height[i]左边的最大值=LMArr[i]
  }

  for (let i = height.length - 1; i >= 0; i--) { // 第二个遍历找到height每一项对应的右边的最大值 
    rightMax = Math.max(height[i], rightMax);
    RMArr.unshift(rightMax); // height[i]右边的最大值=LMArr[i]
  }

  for (let i = 0; i < height.length; i++) { // 第三个遍历判断每一项能装但是水
    let tmp = Math.min(LMArr[i], RMArr[i]);
    if (height[i] < tmp) sum += tmp - height[i];
  }

  return sum;
}
思路2:双指针
 
var trap = function (height) {
  let leftMax = 0; // 记录左边界的最大值
  let rightMax = 0; // 记录右边界的最大值
  let l = 0, r = height.length - 1; // 左右指针
  let sum = 0; // 总共的水
  while (l < r) {
    // 如果左指针的值小于右指针的值 则左指针的值必定小于右边界 此时只需要判断左指针的值跟左边界的差值
    if (height[l] < height[r]) {
      // 判断左指针的值和左边界最大值的大小 如果左边界大 那么可以蓄水 如果左指针的值大
      // 不能蓄水 更新左边界的最大值
      height[l] > leftMax ? (leftMax = height[l]) : sum += (leftMax - height[l]);
      l++;
    } else { // 同样的 如果右指针的值小于左指针的值 那么右指针的值必定小于左边界 此时只需判断右指针和右边界的差值
      // 判断右指针的值和右边界最大值的大小 如果右边界大 那么可以蓄水 如果右指针的值大
      // 不能蓄水 更新右边界的最大值
      height[r] > rightMax ? (rightMax = height[r]) : sum += (rightMax - height[r]);
      r--;
    }
  }
  return sum;
};
原文地址:https://www.cnblogs.com/lanpang9661/p/12720531.html