给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入: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:
输入:height = [4,2,0,3,2,5]
输出:9
提示:
n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法一:(超出时间限制)
class Solution {
public:
int trap(vector<int>& height) {
int size = height.size();
if(size <= 2)
{
return 0;
}
int first_index = height[0] > height[1] ? 0 : 1;
int second_index = height[0] < height[1] ? 0 : 1;
for(int i = 2; i < size; i++)
{
if(height[i] >= height[first_index])
{
second_index = first_index;
first_index = i;
}
else if(height[i] > height[second_index])
{
second_index = i;
}
}
//cout << "first_index = " << first_index << endl;
//cout << "second_index = " << second_index << endl;
int left_index = first_index < second_index ? first_index : second_index;
int right_index = first_index > second_index ? first_index : second_index;
int result = 0;
for(int i = left_index + 1; i < right_index; i++)
{
int single_capacity = height[second_index] - height[i];
if(single_capacity > 0)
{
result += single_capacity;
}
}
//cout << "result = " << result << endl;
vector<int> left_height;
vector<int> right_height;
left_height.assign(height.begin(), height.begin() + left_index + 1);
right_height.assign(height.begin()+right_index, height.end());
result += trap(left_height);
//cout << "left result = " << result << endl;
result += trap(right_height);
//cout << "right result = " << result << endl;
return result;
}
};
方法二:(超出时间限制)
class Solution {
public:
int trap(vector<int>& height) {
int size = height.size();
int result = 0;
for(int i = 1; i < size - 1; i++)
{
int max_left = 0, max_right = 0;
for(int j = 0; j <= i; j++)
{
//if(height[j] > max_left)
//{
//max_left = height[j];
//}
max_left = max(max_left, height[j]);
}
for(int j = i; j < size; j++)
{
//if(height[j] > max_right)
//{
//max_right = height[j];
//}
max_right = max(max_right, height[j]);
}
//int min_heigh = max_left < max_right ? max_left : max_right;
//int current_capacity = min(max_left, max_right) - height[i];
//if(current_capacity > 0)
//{
// result += current_capacity;
//}
result += min(max_left, max_right) - height[i];
}
return result;
}
};
方法三:
该方法是在方法二基础上面的优化。通过遍历两遍,找出对应的坐标,左侧最大值和右侧最大值。
class Solution {
public:
int trap(vector<int>& height) {
if (height.size() < 3)
return 0;
int ans = 0;
int size = height.size();
vector<int> left_max(size), right_max(size);
left_max[0] = height[0];
for (int i = 1; i < size; i++) {
left_max[i] = max(height[i], left_max[i - 1]);
}
right_max[size - 1] = height[size - 1];
for (int i = size - 2; i >= 0; i--) {
right_max[i] = max(height[i], right_max[i + 1]);
}
for (int i = 1; i < size - 1; i++) {
ans += min(left_max[i], right_max[i]) - height[i];
}
return ans;
}
};