一、题意
给定 非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
二、解法
解法一:
动态规划
对于下标i,下雨后水能到达的最大高度等于下标i两边的最大高度的最小值,下标 ii 处能接的雨水量等于下标 ii 处的水能到达的最大高度减去 height[i]。
用两个数组,一个记录下标
≤
i
\leq i
≤i的最大高度leftMax
,一个记录下标
≥
i
\geq i
≥i的最大高度rightMax
。
对于i,比较当前leftMax和rightMax的大小,取最小值,减去height[i],即为接水量。
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
解法二:
双指针法
用left
和right
分别从两边遍历。
用两个变量,一个记录下标
≤
l
e
f
t
\leq left
≤left的最大高度leftMax
,一个记录下标
≥
r
i
g
h
t
\geq right
≥right的最大高度rightMax
。
用height[left]
和height[right]
更新leftMax
和rightMax
比较leftMax
和 rightMax
的大小:
leftMax<rightMax
:ans
加上leftMax-height[left]
,left++
否则:
加上rightMax-height[right]
,right--
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
三、代码
解法一:
int trap(vector<int>& height) {
vector<vector<int> > nh(height.size(),vector<int>(2,0));
int n = height.size();
nh[0][0]=height[0];
for(int i=1;i<n;i++){
nh[i][0] = max(height[i],nh[i-1][0]);
}
nh[n-1][1]=height[n-1];
for(int i=n-2;i>=0;i--){
nh[i][1] = max(height[i],nh[i+1][1]);
}
int ans=0;
for(int i=1;i<n-1;i++){
ans+=max(min(nh[i][0],nh[i][1]) - height[i],0);
}
return ans;
}
解法二:
int trap(vector<int>& height) {
int n = height.size();
int leftMax=0,rightMax=0;
int ans=0;
int left = 0;
int right = n-1;
while(left<right){
leftMax = max(leftMax,height[left]);
rightMax = max(rightMax,height[right]);
if(height[left]<height[right]){
ans+=max(leftMax-height[left],0);
++left;
}
else{
ans+=max(rightMax-height[right],0);
right--;
}
}
return ans;
}
四、引用
[1] leetcode:42. Trapping Rain Water
[2] leetcode:42. Trapping Rain Water