题目:
1.首先是面积法:
算出每一层的面积相加之后减去柱状图的面积就是雨水面积,这个方法是真的秒,一开始还真想不到。
第一层高度为1;
2.动态规划法:
本质上是暴力算法的优化。
对于下标 i,水能到达的最大高度等于下标 i 两边的最大高度的最小值,下标 i处能接的水的量等于下标 i 处的水能到达的最大高度减去height【i】。
因此就用两个数组分别记录下标i时左边的最大值和右边的最大值。
3.单调栈
之前的笔记里面使用过。
维护一个单调递减的栈。当遇到比栈顶元素大的元素时,逐一比对计算。(这种数组会出现驼峰的数字一定要考虑单调栈)
三种算法C++,加测试:
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
//单调栈法
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0;
stack<int> stk;
int n = height.size();
for (int i = 0; i < n; ++i) {//栈中存储的是下标
while (!stk.empty() && height[i] > height[stk.top()]) {
int top = stk.top();
stk.pop();
if (stk.empty()) {
break;
}
int left = stk.top();
int currWidth = i - left - 1;
int currHeight = min(height[left], height[i]) - height[top];
ans += currWidth * currHeight;
}
stk.push(i);
}
return ans;
}
};
动态规划法:
//class Solution{
// public:
// int trap(vector<int>& height){
// //用一个数组存储下标i左边的最大值,另一个数组存储下标i右边的最大值
// int n = height.size();
// if(n==0){
// return 0;
// }
// vector<int> leftMax(n);
// vector<int> rightMax(n);
//
// leftMax[0] = height[0];
// rightMax[n-1] = height[n-1];
//
// for(int i=1;i<n;i++){//计算下标i对应左右的最大值
// leftMax[i] = max(leftMax[i-1],height[i]);
// }
// for (int i = n - 2; i >= 0; --i) {
// rightMax[i] = max(rightMax[i + 1], height[i]);
// }
//
// int sum = 0;//计算
// for(int i=0;i<height.size();i++){
// sum += min(leftMax[i],rightMax[i])-height[i];
// }
//
// return sum;
// }
//};
//面积差值 双指针解法
//class Solution {
//public:
// int trap(vector<int>& height) {
// int i = 0;
// int j = height.size()-1;
// int sum = 0;
// int h = 1;//计算当层高度
// while(i<=j){
// while(i<=j&&height[i]<h){
// i++;
// }
// while(i<=j&&height[j]<h){
// j--;
// }
// if(h!=0){
// sum+= j-i+1;
// }
// h++;
// }
//
//
// int volum = 0;
// for(int i=0;i<height.size();i++){
// volum += height[i];
// }
//
// return sum - volum;
// }
//};
int main(){
vector<int> height = {0,1,0,2,1,0,1,3,2,1,2,1};
Solution solution;
cout<<solution.trap(height)<<endl;
}