https://leetcode-cn.com/problems/trapping-rain-water/
暴力法优化(时间O(N),空间O(N))
算法思想:接得雨水总量等于每一个柱子所接雨水之和,每一个柱子能接到的雨水 = min(left_max[i], right_max[i]) - height[i], left_max[i]表示i左边的最大值,right_max[i]表示i右边的最大值
预先求得每一个元素height[i]对应的left_max和right_max,相比于暴力法在遍历每一个元素的for循环内部求解left_max和right_max,将时间复杂度从O(n的平方)降低到O(n)
class Solution {
public:
//算法思想:接得雨水总量等于每一个柱子所接雨水之和,
//每一个柱子能接到的雨水 = min(left_max[i], right_max[i]) - height
int trap(vector<int>& height) {
int len = height.size();
if(len == 0) return 0;
vector<int> left_max(len, 0); //left_max[i]表示i左边的最大值(包含i)
vector<int> right_max(len, 0); //right_max[i]表示i右边的最大值(包含i)
int ans = 0;
//预先求得每一个元素height[i]对应的left_max和right_max,相比于暴力法在遍历每一个
//元素的for循环内部求解left_max和right_max,将时间复杂度从O(n的平方)降低到O(n)
left_max[0] = height[0];
for(int i = 1; i < len; i++) {
left_max[i] = max(height[i], left_max[i - 1]);
}
right_max[len - 1] = height[len - 1];
for(int i = len - 2; i >= 0; i--) {
right_max[i] = max(height[i], right_max[i + 1]);
}
for(int i = 0; i < len; i++) {
ans += min(left_max[i], right_max[i]) - height[i];
}
return ans;
}
};
双指针法(时间O(N),空间O(1))
算法思想:接得雨水总量等于每一个柱子所接雨水之和,每一个柱子能接到的雨水 = min(left_max[i], right_max[i]) - height[i], left_max[i]表示i左边的最大值,right_max[i]表示i右边的最大值
双指针法:相比于预先求得left_max和right_max数组,可分别维护left_max(从0开始,从左往右)和right_max(从len - 1开始,从右往左)指针, 当left_max <= right_max时, 从左往右依次计算每个柱子接水量,否则, 从右往左依次计算每个柱子接水量,直到二者相遇*/
class Solution {
public:
//双指针
/*算法思想:接得雨水总量等于每一个柱子所接雨水之和,每一个柱子能接到的雨水 = min(left_max, right_max) - height
双指针法:相比于预先求得left_max和right_max数组,可分别维护left_max(从0开始,从左往右)
和right_max(从len - 1开始,从右往左)指针,
当left_max <= right_max时, 从左往右依次计算每个柱子接水量,
否则, 从右往左依次计算每个柱子接水量,直到二者相遇*/
int trap(vector<int>& height) {
int len = height.size();
if(len == 0) return 0;
int left_max = height[0]; //left_max[i]表示i左边的最大值(包含i)
int right_max = height[len - 1]; //right_max[i]表示i右边的最大值(包含i)
int left = 0;
int right = len - 1;
int ans = 0;
while(left < right) {
if(height[left] <= height[right]) {
//height[left] > left_max ? (left_max = height[left]) : ans += (left_max - height[left]);
left_max = max(height[left], left_max);
ans += left_max - height[left];
left++;
}else {
//height[right] > right_max ? (right_max = height[right]) : ans += (right_max - height[right]);
right_max = max(height[right], right_max);
ans += right_max - height[right];
right--;
}
}
return ans;
}
};