LeetCode 热题 HOT 100 Java题解——42. 接雨水

这篇博客详细介绍了LeetCode热门题目42-接雨水的解决方案,包括动态规划数组法和动态规划双指针法。动态规划数组法通过维护左右两侧的最大高度来计算雨水量,而双指针法则优化了空间复杂度,仅遍历一次数组即可。两种方法的时间复杂度均为O(n),但空间复杂度不同,动态规划双指针法达到了O(1)。
摘要由CSDN通过智能技术生成

42. 接雨水

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

avatar

示例:

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

动态规划数组

按列计算雨水面积,当前列的雨水量是左右两边最高柱子中较矮的那根决定的(木桶原理),雨水量等于较矮的那根高度高于当前列高度的量,因此可以维护两个数组,分别表示 i i i列左边最高的柱子和右边最高的柱子,开始时,先初始化两个表,之后再遍历一遍柱子,用变量 s u m sum sum累加总雨水量:

class Solution {
    public int trap(int[] height) {
        int[] max_left = new int[height.length], max_right = new int[height.length];
        int sum = 0;
        for (int i = 1; i < height.length - 1; i++) max_left[i] = Math.max(max_left[i - 1], height[i - 1]);
        for (int i = height.length - 2; i >= 0; i--) max_right[i] = Math.max(max_right[i + 1], height[i + 1]);
        for (int i = 1; i < height.length - 1; i++) {
            int min = Math.min(max_left[i], max_right[i]);
            if(min > height[i]) sum += min - height[i];
        }
        return sum;
    }
}
复杂度分析
  • 时间复杂度: O ( n ) O(n) O(n)

    三次遍历 h e i g h t height height数组, O ( 3 n ) = O ( n ) O(3n) = O(n) O(3n)=O(n)

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

    两个表长度的额外空间 O ( 2 n ) = O ( n ) O(2n) = O(n) O(2n)=O(n)

动态规划双指针

对上面代码的优化,由于动态规划数组中的值每个也只使用了一次,因此可以考虑使用滚动指针, l e f t left left r i g h t right right分别从两边向内遍历, s u m sum sum分别累加在 l e f t left left r i g h t right right处的雨水面积:

  1. 开始判断 h e i g h t [ l e f t − 1 ] height[left - 1] height[left1] h e i g h t [ r i g h t + 1 ] height[right + 1] height[right+1]的高度,如果前者小,就更新 m a x l e f t max_left maxleft的值并移动 l e f t + + left++ left++,因为 m a x l e f t max_left maxleft h e i g h t [ l e f t − 1 ] height[left - 1] height[left1]更新而来,所以只要左一直小于右, m a x l e f t max_left maxleft就一定是两边最高柱子中最矮的。
  2. 如果左边柱子高于右边了,就开始移动 r i g h t right right,只要右边小,同理 m a x r i g h t max_right maxright就一定是两边最高柱子中最矮的。

用这样的方法使得两个指针就很好的一遍遍历完数组了。、

class Solution {
    public int trap(int[] height) {
        int sum = 0, max_left = 0, max_right = 0, left = 1, right = height.length - 2;
        for (int i = 1; i < height.length - 1; i++) {
            if(height[left - 1] < height[right + 1]) {
                max_left = Math.max(height[left - 1], max_left);
                if (max_left > height[left]) sum += max_left - height[left];
                left++;
            }else {
                max_right = Math.max(height[right + 1], max_right);
                if(max_right > height[right]) sum += max_right - height[right];
                right--;
            }
        }
        return sum;
    }
}
复杂度分析
  • 时间复杂度: O ( n ) O(n) O(n)

    一次遍历 h e i g h t height height数组, O ( n ) O(n) O(n)

  • 空间复杂度: O ( 1 ) ) O(1)) O(1))

    常数级变量 O ( 1 ) ) O(1)) O(1))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值