zoukankan      html  css  js  c++  java
  • [LeetCode]42. 接雨水(双指针,DP)

    题目

    给定 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;
        }
    }
    
  • 相关阅读:
    Linux shell 获取当前时间之前N天
    python 连接oracle 数据库
    Python 连接mysql
    python字符串反转
    java基础之数据类型转换
    java 基础之数据类型
    使用sublime编辑器编辑eclpse跑tomcat的项目不及时更新问题的解决方法
    日常git命令
    快速排序,按某个属性,或按“获取排序依据的函数”,来排序
    Gulp初识
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/11333317.html
Copyright © 2011-2022 走看看