题意理解
给定高低不均匀的一组柱子高度,计算下雨后可以接住的雨水数量。
问题分析
用栈。
思路还是放在入栈和出栈上。
如果是下降,那么直接入栈。
如果是上升,开始处理接住的雨水数量。每上升一次,计算接住的数量,一层一层往上累加
用动规。
思路是两个动规预处理
分别计算每个点的左边最高处和右边最高处,min(左边最高处,右边最高处)- 这个点的高度,大于0就是雨水集赞的高度。一列一列往右扩展。
左边最高处可以动规计算出来,右边最高处可以动规计算出来。
其他
https://leetcode-cn.com/problems/trapping-rain-water/submissions/
此题甚难,明白了练好算法是要花时间的,如果喜欢,花再多的时间也愿意啊。
20210430: 一年了,还是刷算法来的安心。
链接
class Solution {
public:
int trap(vector<int>& height) {
stack<int> my_stack; //特殊栈
int len = height.size();
int rains = 0;
for (int i = 0; i < len; i ++) {
while(!my_stack.empty() && height[i] > height[my_stack.top()]) {
int top = my_stack.top(); //获取底盘
my_stack.pop();
if (my_stack.empty()) { //取不到第二个栈元素,说明是靠边了,去掉
break;
}
int dis = i - my_stack.top() - 1; // i 是右边沿 my_stack.top() 是左边沿
int depth = min(height[i], height[my_stack.top()]) - height[top];
rains += dis * depth;
}
my_stack.push(i);
}
return rains;
}
};
class Solution {
public:
int trap(vector<int>& height) {
int len = height.size();
if (len <= 1) return 0;
vector<int> leftMax(len); //左高度
leftMax[0] = 0;
for (int i = 1; i < len; i ++) {
leftMax[i] = leftMax[i-1] > height[i-1] ? leftMax[i-1] : height[i-1];
//cout << leftMax[i] << '\t';
}
//cout << endl;
vector<int> rightMax(len);
rightMax[len-1] = 0;
for (int i = len-2; i >= 0; i --) {
rightMax[i] = rightMax[i+1] > height[i+1] ? rightMax[i+1] : height[i+1];
//cout << rightMax[i] << '\t';
}
//cout << endl;
int res = 0;
for (int i = 1; i < height.size()-1; i++) {
if (leftMax[i] == 0) continue;
if (rightMax[i] == 0) continue;
int lowHeight = min(leftMax[i], rightMax[i]);
res += (lowHeight > height[i]) ? (lowHeight - height[i]) : 0;
//cout << leftMax[i] << '\t' << rightMax[i] << '\t' << height[i] << '\t' << res << '\n';
}
return res;
}
};