给定一个数组, 表示高度,计算存水量。
例子:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
方法1:动态规划
int trap(vector<int>& height) {
if (height.empty()) { return 0; }
int n = height.size();
int left_max[n], right_max[n];
left_max[0] = height[0];
right_max[n - 1] = height[n - 1];
for (int i = 1; i < n; ++i) {
left_max[i] = max(left_max[i - 1], height[i]);
}
for (int i = n - 2; i >= 0; --i) {
right_max[i] = max(right_max[i + 1], height[i]);
}
int res = 0;
for (int i = 1; i < n - 1; ++i) {
res += min(left_max[i], right_max[i]) - height[i];
}
return res;
}
方法2:使用栈
int trap(vector<int>& height) {
int waiter = 0;
stack<int> s; // save idx
for(int i = 0; i < height.size(); ++i) {
while(!s.empty() && height[s.top()] < height[i]) {
// 凹形计算waiter, (height[s.top()], height[mid], height[i])组成凹形
int mid = s.top();
s.pop();
if(!s.empty()) {
waiter += (min(height[s.top()], height[i]) - height[mid]) * (i - s.top() - 1);
}
}
s.push(i);
}
return waiter;
}
方法3:双指针
int trap(vector<int>& height)
{
int left = 0, right = height.size() - 1;
int ans = 0;
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;
}