LeetCode接雨水

这篇博客介绍了如何解决LeetCode上的雨水填充满柱子问题,提供了两种不同的解决方案。思路一是通过两次遍历计算左右两侧的最大高度来确定每个位置的积水,思路二是利用栈模拟过程,动态计算局部的积水。这两种方法都是基于柱子高度数组来求解储水量,并给出了相应的C++实现代码。
摘要由CSDN通过智能技术生成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
给定 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
1 <= n <= 2 * 10^4
0 <= height[i] <= 10^5

思路一:当前位置的积水量怎么求呢,当然是与左右两个位置有关系的,看5号位置,当前的储水量只与左边的最高和右边的最高有关(因为当前位置的水的高度,是由两边同时包起来才会被存储,往上数一格,只要能被包住那就可以存储水),同样四号位置,也是只与最左边最高即3号位和最右边最高即7号位有关。求法:min(左边最高,右边最高)-当前高度。
所以求法就是:从左到右扫一次,记录左边最高。从右向左扫一次,记录右边最高,就可以直接求最小值,减去当前的高度,累加起来即可。
在这里插入图片描述

class Solution {
public: 
    int i;
    int ans;
    int left[20005], right[20005];
    int trap(vector<int>& height) {
        left[0] = height[0];
        for (i = 1; i < height.size(); i++){
            left[i] = max(left[i - 1], height[i]);
        }
        for (i = height.size() - 1; i >= 0; i--)
        {
            right[i] = max(right[i + 1], height[i]);
        }
        for (i = 0; i < height.size(); i++){
            ans += min(left[i], right[i]) - height[i];
        }
        return ans;
    }
};

思路二:
和思路一不同的是,上面是一次性求出结果。即把当前最高能存储水的高度直接求出,而思路二就是只求局部的。因为当前的位置如果能存储水,那么两边一定有比它高的。还是上面的图,看位置5,他两边是高度1,那么当前就能得到高度为1的储水量,而4、5、6此时就是平行的(高度为1)。此时他们的储水量就可以用(7-3-1)–>(长度)*(两边高度的最小(3)-当前的高度(1))得出。用栈来模拟这个过程,如果当前的高度小于栈顶的高度直接入栈。反之,此时的栈顶元素就是两个都比他高的块夹住的。就可以求一下局部的储水量(上面的求法),弹出栈顶元素(因为求完局部,此时的栈顶元素就没有了意义(因为已经把空缺的部分的水算了出来)–>就像5位置)。然后把当前的元素入栈。一直到最后一个元素。

class Solution {
public:
    int ans, now, top, ans1, ans2, ans3;
    stack<int> a;
    int trap(vector<int>& height) {
        while (now < height.size()){
            while (!a.empty() && height[now] > height[a.top()]){
                ans3 = a.top();
                a.pop();
                if (a.empty()) break;
                ans1 = now - a.top() - 1;
                ans2 = min(height[now], height[a.top()]) - height[ans3];
                ans += ans2 * ans1;
            } 
            a.push(now);
            now++;
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值