LeetCode刷题笔记 42

题目:接雨水。给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
在这里插入图片描述
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

方法一:暴力法
从左到右遍历数组,找到当前元素左侧最大值以及右侧最大值,取最小减去自身即为当前元素积累的面积(如果自身就是那个最小的最大值则减完为0)

class Solution {
    public int trap(int[] height) {
        int ans = 0;
        int size = height.length;
        for (int i = 1; i < size - 1; i++) {
            int max_left = 0, max_right = 0;
            for (int j = i; j >= 0; j--) { //Search the left part for max bar size
                max_left = Math.max(max_left, height[j]);
            }
            for (int j = i; j < size; j++) { //Search the right part for max bar size
                max_right = Math.max(max_right, height[j]);
            }
            ans += Math.min(max_left, max_right) - height[i];
        }
        return ans;
    }
}

时间复杂度: O(n2)。数组中的每个元素都需要向左向右扫描。
空间复杂度: O(1)

方法二:双指针
解法一:
水坑的深度总是由短边决定
只要right高度>left高度,积水高度将由left_max决定,当前高度比left_max小,则面积+=left_max-当前高度,否则当前高度赋值为left_max。
积水高度将由left_max决定的原因:
只要right高度>left高度,两种情况:
(1)上一步操作是–right;那么left指向值的一定是left_max
(2)上一步操作是++left;那么right指向值的一定是right_max且比left_max大
不管哪种情况,此时right高度一定大于等于left_max

class Solution {
    public int trap(int[] height) {
        int left = 0, right = height.length - 1;
        int ans = 0;
        int left_max = 0, right_max = 0;
        while (left < right) {
            if (height[left] < height[right]) {
                if(height[left]>=left_max)
                    left_max = height[left];
                else
                    ans += left_max - height[left];
                ++left;
            }
            else {
                if(height[right]>=right_max)
                    right_max = height[right];
                else
                    ans += right_max - height[right];
                --right;
            }
        }
        return ans;
    }
}

解法二:
l_max 和 r_max 代表的是 height[0…left] 和 height[right…end] 的最高柱子高度。
如果l_max < r_max,不管这个 r_max是不是右边最大的都不重要,重要的是height[left]能够装的水只和l_max有关。

class Solution {
    public int trap(int[] height) {
        int n = height.length;
        if(n == 0) return 0;
        int left = 0, right = n - 1;
        int ans = 0;

        int l_max = height[0];
        int r_max = height[n - 1];

        while (left <= right) {
            l_max = Math.max(l_max, height[left]);
            r_max = Math.max(r_max, height[right]);

            // ans += min(l_max, r_max) - height[i]
            if (l_max < r_max) {
                ans += l_max - height[left];
                left++; 
            } else {
                ans += r_max - height[right];
                right--;
            }
        }
        return ans;
    }
}

想法最重要,想问题的时候不要被题目中的例子局限住了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值