天天看點

LeetCode題解:42. 接雨水,雙指針,JavaScript,詳細注釋

原題連接配接:https://leetcode-cn.com/problems/trapping-rain-water/

解題思路:

  1. 将每個柱子都當做一個水桶,單獨計算其轉水量,再加和即可得到結果。
  2. 使用兩個指針分别指向左右桶壁。
  3. 假設目前要計算第i個水桶的轉水量,其實我們隻關心它的左右桶壁中較低的一個。
  4. 第i個水桶的指針隻要選取從左右桶壁中較小的一個,就保證了目前的桶壁高度必然比另一側的所有高度都小,即可用來計算目前桶的轉水量。
  5. 完成計算後,把目前桶的指針向内移動,判斷并計算下一個桶的轉水量即可。
/**
 * @param {number[]} height
 * @return {number}
 */
var trap = function (height) {
  let result = 0; // 存儲結果
  // 目前桶桶壁高度
  let leftMax = height[0]; // 目前桶左側最高桶壁
  let rightMax = height[height.length - 1]; // 目前桶右側最高桶壁
  // 目前桶桶壁索引,同時也是用于計算目前裝水數量的水桶索引
  let left = 1; // 目前桶左側最高桶壁的索引
  let right = height.length - 2; // 目前桶右側最高桶壁的索引

  // 兩個指針向内推進,計算裝水總量
  // 兩個指針相等時也要計算,否則會遺漏一個水桶
  while (left <= right) {
    // 對于單個水桶來說,它其實隻關心最低的桶壁是哪個
    // 而已知的左右桶壁中較小的那個,必然是目前桶的最小桶壁
    // 同時較小的指針指向的就是目前要計算的桶,直接計算目前桶的可裝水量即可
    // 完成計算後将目前指針向内移動一步,目前所使用的桶壁高度,需要同時更新
    if (leftMax < rightMax) {
      // 在移動之前先更新目前桶壁的高度
      // 如果目前桶底高度大于桶壁,計算的轉水量會為0
      leftMax = Math.max(height[left], leftMax);
      // 計算目前轉水量之後,将指針向内移動一位
      result += leftMax - height[left++];
    } else {
      rightMax = Math.max(height[right], rightMax);
      result += rightMax - height[right--];
    }
  }

  return result;
};