单调栈专题之 leetcode 42. 接雨水

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

示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

提示:
n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:
方法1: 暴力
很明显每个柱子顶部可以储水的高度为:该柱子的左右两侧最大高度的较小者减去此柱子的高度。
因此我们只需要遍历每个柱子,累加每个柱子可以储水的高度即可。
此方法非常好理解,直接看下述👇代码中的注释即可。

方法2: 单调栈
简单来说就是当前柱子如果小于等于栈顶元素,说明形不成凹槽,则将当前柱子入栈;反之若当前柱子大于栈顶元素,说明形成了凹槽,于是将栈中小于当前柱子的元素pop出来,将凹槽的大小累加到结果中。

具体思路清参考:
甜姨的题解。
https://mp.weixin.qq.com/s/f9ebzbwymR8jQeUDxjeCDA

方法3:面积做差。
在这里插入图片描述
解法来源:参考lc 宫水三叶,详情请见
https://leetcode-cn.com/problems/volume-of-histogram-lcci/solution/gong-shui-san-xie-yi-ti-si-jie-po-su-yu-sqadp/

//暴力

class Solution {
    public int trap(int[] height) {
        int res = 0;
        // 遍历每个柱子
        for (int i = 1; i < height.length - 1; i++) {
            int leftMax = 0, rightMax = 0;
            // 计算当前柱子左侧的柱子中的最大高度
            for (int j = 0; j <= i; j++) {
                leftMax = Math.max(leftMax, height[j]);
            }
            // 计算当前柱子右侧的柱子中的最大高度
            for (int j = i; j < height.length; j++) {
                rightMax = Math.max(rightMax, height[j]);
            }
            // 结果中累加当前柱子顶部可以储水的高度,
            // 即 当前柱子左右两边最大高度的较小者 - 当前柱子的高度。
            res += Math.min(leftMax, rightMax) - height[i];
        }
        return res;
    }
}

//单调栈
class Solution {
    public boolean find132pattern(int[] nums) {

        Stack<Integer> s = new Stack<Integer>();
        int n = nums.length;
        int k = Integer.MIN_VALUE;

        for (int i = n - 1; i >= 0; i--) {
            if (nums[i] < k) {
                return true;
            }
            //自主控制弹出,来实现单调栈
            while ((!s.empty ()) && (s.peek() < nums[i])) {
                k = Math.max (k, s.pop());
            }
            s.push (nums[i]);
        }
        return false;
    }
}

//面积作差
class Solution {
    public int trap(int[] height) {

        //spcial

        int sum = 0;
        int len = height.length;
        int max = 0;

        for (int i = 0; i < len; i++) {
            sum += height[i];
            max = Math.max (height[i], max);
        }

        int full = max * len;

        int lSum = 0;
        max = 0;
        for (int i = 0; i < len; i++) {
            max = Math.max (height[i], max); 
            lSum += max;
        }

        int rSum = 0;
        max = 0;
        for (int i = len - 1; i >= 0; i--) {
            max = Math.max (height[i], max); 
            rSum += max;
        }

        return  rSum + lSum - full - sum;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值