【LeetCode】42. Trapping Rain Water 接雨水 (C++)
- 作者: 负雪明烛
- id: fuxuemingzhu
- 个人博客:http://fuxuemingzhu.cn/
题目地址:https://leetcode-cn.com/problems/string-to-integer-atoi/
题目描述
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1].
In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
题目大意
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
解题方法
暴力求解
让我们求总的能接多少雨水,这个题有两种解法,一种是每个位置都去判断能接多少雨水,一种是每个区间去判断接多少雨水。
最简单的暴力解法,求每个位置的储水量:
- 遍历每个位置,找到这个位置左边和右边的最高柱子高度;
- 求两个最高柱子中取最矮的高度(短板效应,短板决定盛水量);
- 减去当前柱子的高度就是储水量。
这个时间复杂度是O(N^2),会超时。
C++代码如下。
class Solution {
public:
int trap(vector<int>& height) {
const int N = height.size();
int res = 0;
auto begin = height.begin();
auto end = height.end();
for (int i = 0; i < N; ++i) {
int left_max = *max_element(begin, begin + i + 1);
int right_max = *max_element(begin + i, end);
res += min(left_max, right_max) - height[i];
}
return res;
}
};
保存左右最大值
在上面的暴力解法中,我们知道在每个位置都要求其左右的最大柱子的高度,因此是不是可以更快速的求出来这个值呢?
在很多题目里面,都有这种做法,为了能找出每个位置左右的最大值,可以提前计算并保存。比如,使用left_max和right_max数组,分别保存每个位置的左右两边的最大高度。计算时包含了当前位置,目的是防止出现两边的柱子比当前的位置矮,减的时候出现负值。
使用两边的高度的最小值 - 当前柱子的高度就是该位置的储水量。
C++代码如下:
class Solution {
public:
int trap(vector<int>& height) {
const int N = height.size();
int res = 0;
vector<int> left_max(N, 0);
vector<int> right_max(N, 0);
for (int i = 0; i < N; ++i) {
left_max[i] = i == 0 ? height[i] : max(left_max[i - 1], height[i]);
}
for (int i = N - 1; i >= 0; --i) {
right_max[i] = i == N - 1 ? height[i] : max(right_max[i + 1], height[i]);
}
for (int i = 0; i < N; ++i) {
res += min(left_max[i], right_max[i]) - height[i];
}
return res;
}
};
单调栈
如果你考虑的是一个区间能接多少雨水的话可以使用单调栈。
考虑单调栈的原因是我们从左向右看的时候,发现只有先下降、后上升的情况,才会存储水。
图片来源甜姨的题解:

我们看到每次都要向左边找到左边最高的柱子,然后求这个区间内的面积。

我们看到其实是一层一层的向上累计的。
那么,我们使用一个单调递减栈,每次遇到一个新的位置,都把栈中的元素遍历出来,找出所有的比当前位置矮的,累积计算这部分面积。
计算面积公式:(两柱子的最小高度 - 两柱子之间的最大高度)* 距离。
C++代码如下:
class Solution {
public:
int trap(vector<int>& height) {
const int N = height.size();
if (N < 3) return 0;
int res = 0;
stack<int> st;
int idx = 0;
while (idx < N) {
if (st.empty() || height[idx] <= height[st.top()]) {
st.push(idx);
idx ++;
} else {
int last = st.top(); st.pop();
if (st.empty()) continue;
int distance = idx - st.top() - 1;
res += distance * (min(height[st.top()], height[idx]) - height[last]);
}
}
return res;
}
};
欢迎关注负雪明烛的刷题博客,leetcode刷题800多,每道都讲解了详细写法!
日期
2020 年 4 月 4 日 —— 全国哀悼日
【LeetCode】42. Trapping Rain Water 接雨水 (C++)的更多相关文章
- [LeetCode] 42. Trapping Rain Water 收集雨水
Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...
- leetcode#42 Trapping rain water的五种解法详解
leetcode#42 Trapping rain water 这道题十分有意思,可以用很多方法做出来,每种方法的思想都值得让人细细体会. 42. Trapping Rain WaterGiven n ...
- [array] leetcode - 42. Trapping Rain Water - Hard
leetcode - 42. Trapping Rain Water - Hard descrition Given n non-negative integers representing an e ...
- LeetCode 42. Trapping Rain Water 【两种解法】(python排序遍历,C++ STL map存索引,时间复杂度O(nlogn))
LeetCode 42. Trapping Rain Water Python解法 解题思路: 本思路需找到最高点左右遍历,时间复杂度O(nlogn),以下为向左遍历的过程. 将每一个点的高度和索引存 ...
- LeetCode - 42. Trapping Rain Water
42. Trapping Rain Water Problem's Link ------------------------------------------------------------- ...
- leetCode 42.Trapping Rain Water(凹槽的雨水) 解题思路和方法
Trapping Rain Water Given n non-negative integers representing an elevation map where the width of e ...
- [leetcode]42. Trapping Rain Water雨水积水问题
Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...
- [LeetCode] 42. Trapping Rain Water 解题思路
Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...
- [LeetCode]42. Trapping Rain Water雨水填坑
这个题难点在于无法保证右边是不是有更高的墙可以保证挡住水 双指针可以解决 /* 两边指针保证,保证另外一边肯定有能挡住水的地方. 如果从一边开始,不考虑另一边,是无法保证右边肯定有挡水的墙,如果右边只 ...
随机推荐
- Neville 插值方法
简介 wikipedia: Neville's method 在数学上,Neville 算法是一种计算插值多项式方法,由数学家Eric Harold Neville提出.由给定的n+1个节点,存在一个 ...
- C语言计算fastq文件GC含量2
改进了一下,利用zlib可以读取gz格式的压缩文件,也可以直接计算非压缩格式 #include <stdio.h> #include <stdlib.h> #include & ...
- 57-Palindrome Linked List
Palindrome Linked List My Submissions QuestionEditorial Solution Total Accepted: 46990 Total Submiss ...
- Oracle--计算某一日期为一年中的第几周
我自己实现的脚本: select T31267.CREATED_DATE as F31265, (select to_char(to_date(T31267.CREATED_DATE,'yyyy-mm ...
- 4 — springboot中的jsr303检验
1.导入依赖 <!--JSR303校验的依赖 --> <dependency> <groupId>org.springframework.boot</grou ...
- 用友低代码开发平台YonBuilder首次亮相DevRun开发者沙龙
2020年的今天,没有人会再质疑企业上云的必要性与价值所在.从高科技行业到传统领域,大大小小的企业都希望走在变革道路前列,通过企业云加快业务数字化转型,更好地维护和管理企业数据. 然而,大多数企业都很 ...
- Spark(十二)【SparkSql中数据读取和保存】
一. 读取和保存说明 SparkSQL提供了通用的保存数据和数据加载的方式,还提供了专用的方式 读取:通用和专用 保存 保存有四种模式: 默认: error : 输出目录存在就报错 append: 向 ...
- flink01--------1.flink简介 2.flink安装 3. flink提交任务的2种方式 4. 4flink的快速入门 5.source 6 常用算子(keyBy,max/min,maxBy/minBy,connect,union,split+select)
1. flink简介 1.1 什么是flink Apache Flink是一个分布式大数据处理引擎,可以对有限数据流(如离线数据)和无限流数据及逆行有状态计算(不太懂).可以部署在各种集群环境,对各种 ...
- Vue面试专题(未完)
1.谈一下你对MVVM原理的理解 传统的 MVC 指的是,用户操作会请求服务端路由,路由会调用对应的控制器来处理,控制器会获取数 据.将结果返回给前端,页面重新渲染. MVVM :传统的前端会将数 ...
- 安全相关,xss
XSS XSS,即 Cross Site Script,中译是跨站脚本攻击:其原本缩写是 CSS,但为了和层叠样式表(Cascading Style Sheet)有所区分,因而在安全领域叫做 XSS. ...