Trapping Rain Water
Solution 1
这个题乍一看应该是之前存水问题的变体,所以还是一个使用双指针维护的问题。我一开始还是希望和存水问题一样的思路,但是计算水量的过程变成了一个子遍历。后面发现每一个格的水量计算是线性时间的:找到两侧高于当前占位的最高值中较小的一个,计算差值即可,即min(maxLeft, maxRight) - height[current]
。因此需要对双指针的遍历逻辑进行改动,增加两个分别维护左侧最大和右侧最大的状态量,左右指针分别有可能更新各自一侧的最大值。因此遍历逻辑如下:
- 如果当前左侧指针更小,那么必然左侧计算更加稳妥(因为计算结果依赖于较短的一侧),考察左侧是替换最大值还是计算存水量
- 对应地,如果右侧指针更小,右侧计算更加稳妥,考察右侧
- 时间复杂度: O ( n ) O(n) O(n), n n n为输入长度,双指针遍历
- 空间复杂度: O ( 1 ) O(1) O(1),仅维护常数个状态变量
class Solution {
public:
int trap(vector<int>& height) {
int left = 0, right = height.size() - 1;
int ans = 0;
int maxLeft = 0, maxRight = 0;
while (left < right) {
// cout << left << ": " << height[left] << " " << maxLeft << " -- " << right << ": " << height[right] << " " << maxRight << " -- " << ans << endl;
if (height[left] < height[right]) {
// 此时,所有的位置的计算以左侧为准,但是只有左侧的才能计算准确
if (height[left] > maxLeft) {
maxLeft = height[left];
}
else {
ans += maxLeft - height[left];
}
left ++;
}
else {
// 同理,此时所有的计算以右侧为准,但只有右侧的才能计算准确
if (height[right] > maxRight) {
maxRight = height[right];
}
else {
ans += maxRight - height[right];
}
right --;
}
}
return ans;
}
};
Solution 2
Solution 1的Python实现
class Solution:
def trap(self, height: List[int]) -> int:
left = 0
right = len(height) - 1
ans = 0
maxLeft = 0
maxRight = 0
while left < right:
if height[left] < height[right]:
if height[left] > maxLeft: maxLeft = height[left]
else: ans += maxLeft - height[left]
left += 1
else:
if height[right] > maxRight: maxRight = height[right]
else: ans += maxRight - height[right]
right -= 1
return ans