leetcode42.接雨水 动态规划、双指针

leetcode42.接雨水

题目描述

在这里插入图片描述

思路

动态规划:

雨水能存储多少,取决于较短的那一边的高度,所以我们可以列举出每一列左右两边最短的“木板”,从而即可求解每一列最多存储多少雨水。

时间复杂度:O(n)
空间复杂度:O(n)

class Solution {
    public int trap(int[] height) {
        int n = height.length;
        //dp[i][0] 左边  dp[i][1]右边
        int[][] dp = new int[n][2];

        //dp[0][0] = 0;
        //求每一列左边的最高的墙
        for(int i = 1; i < n; i++) {
            dp[i][0] = Math.max(height[i - 1], dp[i - 1][0]);
        }
        //dp[n - 1][1] = 0;
        //求每一列右边最高的墙
        for(int i = n - 2 ; i >= 0; i--) {
            dp[i][1] = Math.max(height[i + 1], dp[i + 1][1]);
        }

        int ans = 0;

        for(int i = 1; i < n - 1; i++) {
            //每一列的存水量取决于较小的那一边的高度差
            int temp = Math.min(dp[i][0] - height[i],
                     dp[i][1] - height[i]);
            //小于0的情况即存不了雨水(会漏出去)
            ans += temp < 0 ? 0 : temp;
        }

        return ans;
    }
}

双指针解法:

  1. 由于每一列雨水存量取决于较短的一边,所以我们只需要让左右两边的最大值中的那个较小值是确定的,则可以得知当前列的存水量。
  2. 在动态规划解法中,我们左右分别遍历了一遍才得知每列左右的最大值分别是多少,即我们从左边遍历就能确保左边的最大值,从右边遍历我们就能确保右边的最大值。
  3. 结合上面的解题思路,我们可以得出最终方案:当左边的最大值小于右边的最大值,我们求出左指针所在的点的存水量。移动左指针,当右边的最大值小于左边的最大值,我们求出右指针所在的点的存水量,移动右指针。

时间复杂度:O(n)
空间复杂度:O(1)

class Solution {
    public int trap(int[] height) {
        int n = height.length;
        if(n == 0) return 0;
        
        int l = 0;
        int r = n - 1;
        //右最大值
        int lm = height[l];
        //左最大值
        int rm = height[r];
        int ans = 0;
		
        while(l < r) {
            if(lm < rm) {
                //更新l位置指针左边的最高点
                lm = Math.max(lm, height[++l]);
                ans += lm - height[l];
            } else {
                //更新r位置指针右边的最高点
                rm = Math.max(rm, height[--r]);
                ans += rm - height[r];
            }
        }
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值