題目
https://leetcode-cn.com/problems/trapping-rain-water/
思路
棧的做法:維護一個棧,這個棧其實就是一個遞減的水柱下標的集合,但遇到一個新的水柱比當前棧頂水柱高,那麼就有積水了,難點是要理解如何求出這些積水(長乘寬)。
AC代碼
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
class Solution {
public:
int trap(vector<int>& height) {
/*暴力法
int res = 0;
//按列算,首尾不用算,默認接不到水,
for(int i = 1;i < height.size()-1;i++){
int maxLeft = 0;
int maxRigth = 0;
for(int j = i; j >= 0;j--) { //當前列左邊的最大值
maxLeft = max(maxLeft,height[j]);
}
for (int j = i;j<height.size();j++){//當前列右邊邊的最大值
maxRigth = max(maxRigth,height[j]);
}
//木桶效應
res += min(maxLeft,maxRigth)-height[i];
}
return res;
*/
/*用兩個數組分別保存每個列的左邊最大值和右邊最大值
if(height.size()==0)
return 0; //平臺所謂的健壯性,加上就過了。。不加報一些奇奇怪怪錯誤
int res = 0;
int size = height.size();
vector<int>max_left(size);
vector<int>max_right(size);
max_left[0] = height[0];
for(int i = 1;i<size-1;i++){
max_left[i] = max(height[i],max_left[i-1]);
}
max_right[size-1] = height[size-1];
for(int i = size-2;i>=0;i--)
max_right[i] = max(height[i],max_right[i+1]);
for(int i = 1;i< size-1;i++){
res += min(max_left[i],max_right[i])-height[i];
}
return res;
*/
int res = 0;
stack<int>s; //存放每一列雨水的下標(實際上存儲的下標值對應的水柱是遞減的)
int cur = 0;
while (cur < height.size()){
//當前的水柱大於棧頂的水柱,說明有積水
while (!s.empty() && height[cur] > height[s.top()]){
int top = s.top();
s.pop();
if(s.empty()) //爲空,說明沒有積水
break;
res += (min(height[cur],height[s.top()]) - height[top]) * (cur-s.top()-1); //長乘寬
}
s.push(cur++);
}
return res;
}
};
int main()
{
vector<int>height = {0,1,0,2,1,0,1,3,2,1,2,1};
Solution so;
cout << so.trap(height) << endl;
return 0;
}