接雨水
接雨水这道题目是非常经典的面试题,师兄字节面试的时候似乎就碰到了,所以把它抽出来研究了一下,主要是学习参考Leetcode上的各种评论和题解,总结了四种方法,其中三种是按列计算,还有一种是按区域行计算。最后一种方法虽然复杂度上没有双指针法简单,但是如果给我们的数组是流式输入,无法从后往前进行遍历的话,就只有最后一种方法有用了。
42 接雨水
题目描述
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例1:
输入: height = [ 0 , 1 , 0 , 2 , 1 , 0 , 1 , 3 , 2 , 1 , 2 , 1 ] [0,1,0,2,1,0,1,3,2,1,2,1] [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 ] [4,2,0,3,2,5] [4,2,0,3,2,5]
输出: 9
提示:
-
n = = h e i g h t . l e n g t h n == height.length n==height.length
-
0 < = n < = 3 × 1 0 4 0 <= n <= 3 \times 10^4 0<=n<=3×104
-
0 < = h e i g h t [ i ] < = 1 0 5 0 <= height[i] <= 10^5 0<=height[i]<=105
解法一:暴力法
核心思路
仔细思考每一个单位的雨水高度的特点,可以发现对于每个单位而言,雨水的高度就是该单位左右最高高度中的较小值和自己高度的差(注意要从自己本身找起)。所以用暴力法,找到每一个单位左右最高高度,然后用两者中较小的高度减去自己的高度,然后将所有高度的水的高度相加,就得到了能接的雨水的总量。
关键就在于发现单位处的雨水高度就是左右最高处较小值和自己高度的差。
代码
class Solution{
public:
int trap(vector<int> &height){
int ans = 0;
int n = height.size();
for(int i=1;i<n-1;i++){
int left_high=0 , right_high=0;
for(int j=i;j>=0;j--){
left_high = max(left_high,height[j]);
}
for(int j=i;j<n;j++){
right_high = max(right_high,height[j]);
}
ans += min(left_high,right_high)-height[i]
}
return ans;
}
};
复杂度分析
- 时间复杂度: O ( n 2 ) O(n^2)