42. 接雨水
题目:
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
解答:
拿的官方题解的图:
保存每个下标的left、right值。取小的加起来就是总的雨水量。

双指针:(好难想)
class Solution { public: int trap(vector<int>& height) { int n=height.size(); int le=0,ri=n-1,le_mx=0,ri_mx=n-1,res=0; while(le<ri){ if(height[le]<height[ri]){ if(height[le]>height[le_mx]){ le_mx=le; } else{ res+=height[le_mx]-height[le]; } ++le; } else{//height[le]>=height[ri],那么height[le_max]>=height[le]>=height[ri],所以: //height[le_mx]>height[ri] if(height[ri]>height[ri_mx]){ ri_mx=ri; } else{ res+=height[ri_mx]-height[ri]; } --ri; } } return res; } };
class Solution { public: int trap(vector<int>& height) { if(height.size()==0) 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; } };
单调栈:
维护一个递减栈,栈中保存的是height数组下标,因为蓄水池宽度不一定为1,我们利用数组下标好计算宽度。

class Solution { public: int trap(vector<int>& height) { int n=height.size(); if(n<=2){ return 0; } stack<int> sta; int res=0; int i=0; while(i<n){ while(not sta.empty() and height[i]>=height[sta.top()]){ int cur_top=sta.top(); sta.pop(); // cout<<"pop height["<<cur_top<<"]"<<height[cur_top]<<endl; if(sta.empty()){ break; } res+=(min(height[i],height[sta.top()])-height[cur_top])*(i-sta.top()-1); // cout<<"res="<<res<<endl; } sta.push(i++); // cout<<"push height["<<i-1<<"]"<<height[i-1]<<endl; } return res; } };
进击的小🐴农

浙公网安备 33010602011771号