42. 接雨水

42-接雨水

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

示例 1:

img

1
2
3
输入: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:

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

提示:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

一、动态规划

某个位置$i$能够存储的最大的雨水高度等于$min(leftMax[i],rightMax[i])-height[i]$

其中$leftMax[i]$和$rightMax[i]$分别是指$i$位置左侧最大高度和右侧最大高度

$leftMax[0]$等于$height[0]$,$rightMax[n-1]$等于$height[n-1]$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
int trap(vector<int>& height) {
int n = height.size();
vector<int> leftMax(n);
vector<int> rightMax(n);
leftMax[0] = height[0];
rightMax[n-1] = height[n-1];
for(int i = 1;i < n-1;i++){
leftMax[i] = max(leftMax[i-1],height[i]);
}
for(int i = n-2;i > 0;i--){
rightMax[i] = max(rightMax[i+1],height[i]);
}

int total = 0;
for(int i = 1;i < n-1;i++){
int unit;
// cout<< min(leftMax[i],rightMax[i])<<" ";
unit = min(leftMax[i],rightMax[i])-height[i];
total += unit;
}
return total;
}
};

二、单调栈

单调栈元素大小需要满足递减,即确保$height[left] <= height[stack.top()]$,left是top左边的高度

遍历数组,第$i$个元素,比较一下$height[i]$和栈顶元素的大小,如果$height[i] < height[stack.top()]$,说明形成了凹槽,计算一下宽度,$width = i - left - 1$,高度,$h = min(height[i],height[left])-height[top] $

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public:
int trap(vector<int>& height) {
stack<int> s;
int ans = 0;
int n = height.size();
for(int i = 0;i < n;i++){
while(!s.empty() && height[i] > height[s.top()]){
int top = s.top();
s.pop();
if(s.empty()){
break;
}
int left = s.top();
int width = i - left - 1;
int h = min(height[i],height[left]) - height[top];
// cout<<width * h<<endl;
ans += width * h;
}
s.push(i);
}
return ans;
}
};

方法三:双指针


42. 接雨水
http://example.com/2023/09/13/42-接雨水/
Author
WYX
Posted on
September 13, 2023
Licensed under