题解
方法一:暴力,从左到右遍历一次,当前位置所能接的最大雨水的值为当前位置的左边的最大值和当前位置的右端的最大值的最小值减去当前位置的值。
方法二:先存储好每个位置的左边最大值和右边最大值,其余步骤和方法一一样,他俩应该是互补的,一个时间复杂度高,一个空间复杂度高。
方法三:堆栈 (不太会,不想学了。。。。)
方法四:双指针即边计算,边计算桶的高度,left right 分别指向左右两边,最小值即为当前桶的高度,即可以计算当前值的所能乘的水,如果当前高度大于桶的高度,即不能盛水,并且要更新桶的高度。
代码
方法一
class Solution {
public:
int trap(vector<int>& height) {
//暴力大法好hhh,什么叫做困难题。。。什么是快乐星球
int n = height.size();
int ans = 0;
for(int i = 1; i < n - 1; i++ ){
int max_left = 0,max_right = 0;
for(int j = i; j >= 0; j--){
max_left = max(max_left,height[j]);//寻找在当前位置中左边的最高点
}
for(int j = i; j < n; j++){
max_right = max(max_right,height[j]);//寻找在当前位置中右边的最高点
}
ans += min(max_left,max_right) - height[i];
}
return ans;
}
};
方法二
class Solution{
public:
int trap(vector<int>& height){
int ans = 0;
int n = height.size();
if(n == 0){
return 0;
}
vector<int>left_max(n),right_max(n);//存储中间值
left_max[0] = height[0];
for(int i = 1; i < n; i++){
left_max[i] = max(height[i],left_max[i - 1]);
}
right_max[n - 1] = height[n - 1];
for(int i = n - 2; i >= 0; i--){
right_max[i] = max(height[i],right_max[i + 1]);
}
for(int i = 1; i < n ; i++){
ans += min(left_max[i],right_max[i])-height[i];
}
return ans;
}
};
方法三
class Solution{
public:
int trap(vector<int>&height){
int ans = 0,current = 0;
stack<int> st;
int n = height.size();
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;
}
};
方法四
class Solution{
public:
int trap(vector<int>&height){
int ans = 0;
int left = 0,right = height.size() - 1;
int left_max = 0,right_max = 0;
while(left < right){
if(height[left] < height[right]){
height[left] >= left_max ? (left_max = height[left]) : ans += (left_max - height[left]);
++left;
}else{
height[right] >= right_max ? (right_max = height[right]) : ans += (right_max - height[right]);
--right;
}
}
return ans;
}
};