双指针解决【接雨水】问题

2,098 阅读2分钟

这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战


算法系列, 继续日进一卒~ 之前文章传送门:

本篇将带来双指针算法经典题目之:接雨水问题;

题目

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

image.png

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 
示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

解题思路:

解法 1 :暴力解法

直接按照题目的描述进行,对于数组中的每一个元素,我们找出下雨后水能达到的最高位置,等于两边最大高度较小值减去当前高度的值。

如果i是2 左边的最大值是索引为1的位置,这个位置值是1;右边最大值是3,当前这个位置能够存储多少水,是由短的一边决定的;对于i为3的位置来说,算上当前的索引位置的高度左边的最大值是2。

右边的最大值是还是3,此时左右两边的最小值是2 当前索引处的高度,也是2 这样一来 ans 就是0。说明索引为3的位置不能存储雨水

JS 实现如下:

/**
 * @param {number[]} height
 * @return {number}
 */
var trap = function (height) {
  let res = 0;
  for (let i = 0; i < height.length; i++) {
    let max_letf = 0;
    let max_right = 0;
    // 以当前curr 这个位置为基准,找出左边的边界的最大值 找出右边边界的最大值
    for (let j = i; j >= 0; j--) {
      max_letf = Math.max(max_letf, height[j])
    }
    for (let j = i; j < height.length; j++) {
      max_right = Math.max(max_right, height[j])
    }

    res += Math.min(max_letf, max_right) - height[i]
  }
  return res
};

解法 2 :双指针

当左边最大挡板<右边最大挡板,左边向前挺近,最终值加上当前左最大挡板-当前左指针所指值(相当于左边只要不超过右边,右边最大挡板稳定兜底,左边无脑挺近累加)大于则反之;

JS 实现:

/**
 * @param {number[]} height
 * @return {number}
 */
var trap = function(height) {
    let end = 0 
    let l = 0, r=height.length -1
    let maxl = 0,maxr=0
    while(l < r){
        maxl = Math.max(height[l],maxl)
        maxr = Math.max(height[r],maxr)
        if(maxl < maxr){
            end += maxl - height[l]
            l++
        }else{
            end += maxr - height[r]
            r--
        }
    }
    return end
};

时间复杂度:O(n);双指针,YYDS!

有木有觉得双指针和滑动窗口很像?后续还会带来更多关于双指针的探究~~


OK,以上就是本篇分享~ 撰文不易,点赞鼓励👍👍👍

我是掘金安东尼,公众号同名,日拱一卒、日掘一金,再会~