[LeetCode]42. 接雨水(双指针,DP)

淺唱寂寞╮ 提交于 2019-11-27 00:54:01

题目

给定 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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water

题解

思路1

  • 按列求,对于每一列,若Math.min(左边最高值,右边最高值)>当前列高度,则高度差等于当前列接的雨水。
  • 用DP优化,提前求出lMax、rMax数组,然后DP。时间复杂度O(n),空间复杂度O(n)

思路2(较优,直接看这个)

  • 使用双指针,可以只遍历一次,因为当前列是由“Math.min(左边最高值,右边最高值)”决定的,所以若能确定哪边的最高值更小,则有哪边的最高值就可以了,不需要两边的最高值都知道。
  • 由此,“我们可以认为如果一端有更高的条形块(例如右端),积水的高度依赖于当前方向的高度(从左到右)。当我们发现另一侧(右侧)的条形块高度不是最高的,我们则开始从相反的方向遍历(从右到左)。”
  • lMax,rMax由变量维护,分别表示当前左指针左边的最大值,右指针右边的最大值。代替了数组。故空间复杂度优化至O(1)。

思路1代码(时间复杂度O(n),空间复杂度O(n))

class Solution {
    public int trap(int[] height) {
        if(height==null||height.length==0){
            return 0;
        }
        int len=height.length;
        int[] lMax=new int[len];
        int[] rMax=new int[len];

        lMax[0]=0;
        rMax[len-1]=0;        
        for(int i=1;i<len;++i){
            lMax[i]=Math.max(lMax[i-1],height[i-1]);
        }
        for(int i=len-2;i>=0;--i){
            rMax[i]=Math.max(rMax[i+1],height[i+1]);
        }
        
        int ans=0;
        for(int i=0;i<len;++i){
            int dif=Math.min(lMax[i],rMax[i])-height[i];
            ans=dif>0?ans+dif:ans;
        }
        return ans;
    }
}

思路2代码(较优,时间复杂度O(n),空间复杂度O(1))

class Solution {
    public int trap(int[] height) {
        if(height==null||height.length==0){
            return 0;
        }
        
        int len=height.length;
        int lMax=0;
        int rMax=0;
        
        int l=0;
        int r=len-1;
        int ans=0;
        
        while(l<r){
            if(height[l]<=height[r]){
                if(height[l]>=lMax){
                    lMax=height[l];
                }
                else{
                    ans+=lMax-height[l];
                }
                ++l;
            }
            else{
                if(height[r]>=rMax){
                    rMax=height[r];
                }
                else{
                    ans+=rMax-height[r];
                }
                --r;
            }
        }
       
        return ans;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!