要求:
思路:i处接到的雨水是它左边所有柱子最大高度和右边柱子最大高度的最小值,减去i的柱子高度
法一:动态规划,搞两个数组存左右最大高度
class Solution {
public:
int trap(vector<int>& height) {
int n=height.size();
vector<int> leftmax(n);
vector<int> rightmax(n);
for(int i=1;i<n;++i)
leftmax[i]=max(leftmax[i-1],height[i-1]);
for(int i=n-2;i>=0;--i)
rightmax[i]=max(rightmax[i+1],height[i+1]);
int ans=0;
for(int i=1;i<=n-2;++i)
if(min(leftmax[i],rightmax[i])-height[i]>0)
ans+=min(leftmax[i],rightmax[i])-height[i];
return ans;
}
};
法二:双指针优化,之前做过一题左右乘积是优化了一个数组,这里可以两个都优化。核心思路:如果height[left-1]小于height[right+1]那么left处雨水可以计算了,因为右边比它大了所以只取决于maxleft。反之同理
class Solution {
public:
int trap(vector<int>& height) {
int n=height.size();
int left=1,right=n-2;
int maxleft=0,maxright=0;
int ans=0;
while(left<=right){
if(height[left-1]<height[right+1]){
maxleft=max(maxleft,height[left-1]);
if(maxleft-height[left]>0)
ans+=maxleft-height[left];
++left;
}
else {
maxright=max(maxright,height[right+1]);
if(maxright-height[right]>0)
ans+=maxright-height[right];
--right;
}
}
return ans;
}
};
法三:单调栈。当前比栈顶大就出栈顶,以现在栈顶为左当前为右计算积水;否则入栈
class Solution {
public:
int trap(vector<int>& height){
int ans = 0, current = 0;
stack<int> st;
while (current < height.size()) {
while (!st.empty() && height[current] > height[st.top()]) {
int top = st.top();
st.pop();
if (st.empty())
break;
int distance = current - st.top() - 1;
int bounded_height = min(height[current], height[st.top()]) - height[top];
ans += distance * bounded_height;
}
st.push(current++);
}
return ans;
}
};