原文:42. 接雨水(力扣 面试题) - 每天一个JavaScript小知识@Js中文网 · 码农进阶题库

原文地址:https://www.javascriptc.com/interview-tips/zh_cn/leetcode/leetcode-javascript-solution-042/

题目:

难度:Hard

相关话题:数组双指针

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

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。感谢 Marcos 贡献此图。

示例:

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

思路:

线的雨水收集可以不用优先队列,因为只需要比较当前两端的位置即可。

  1. 比较两端,如果a<b(如果b<a,下面则从b开始)
  2. a开始继续遍历
    • 发现有比它高的墙x,说明这个a点的漏水被堵住了,将这个墙x继续更另一端的值对比x ? b
    • 发现有比它矮的凹口y,说明这个凹口y最多水位能升到a的位置,记录a.height-y.height,继续往下检测
    • 发现和它一样高的,同上
  3. 继续两端对比,递归1
/**
 * @来源: Javascript中文网 - 前端进阶资源教程 https://www.javascriptc.com/
 * @介绍:一个致力于帮助开发者用代码改变世界为使命的平台,每天都可以在这里找到技术世界的头条内容
 * @param {number[]} height
 * @return {number}
 */
var trap = function(height) {
  let leftIdx=0,rightIdx=height.length-1
  let result=0
  while(leftIdx<rightIdx){
    let leftV=height[leftIdx],rightV=height[rightIdx]
    if(leftV<rightV){
      while(leftIdx<rightIdx && height[++leftIdx]<=leftV){
        result+=leftV-height[leftIdx]
      }
      leftV=height[leftIdx]
    }else{
      while(leftIdx<rightIdx && height[--rightIdx]<=rightV){
        result+=rightV-height[rightIdx]
      }
      rightV=height[rightIdx]
    }
  }
  return result
};