装雨水
题意:给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
输入:height = [4,2,0,3,2,5]
输出:9
题解一:DP,预处理前i最大与后i最大即可
int trap(vector<int>& height) {
int n = height.size();
vector<int> left(n), right(n);
for (int i = 0; i < n; ++i) {
if (!i) left[i] = height[i];
else left[i] = max(left[i-1], height[i]);
}
for (int i = n-1; i >= 0; --i) {
if (i == n-1) right[i] = height[i];
else right[i] = max(right[i+1], height[i]);
}
int ret = 0;
for (int i = 1; i < n-1; ++i)
ret += max(0, min(left[i-1], right[i+1]) - height[i]);
return ret;
}
题解二:单调栈,维护单调递减的栈,当不符合递减规则时,取出最小高度(底)以及第二小高度(左边界),计算左边界到右边界的容量,然后更新栈,详情看代码
int trap(vector<int>& height) {
stack<int> s;
int ret = 0;
for (int right = 0; right < height.size(); ++right) {
while (s.size() && height[s.top()] < height[right]) {
int top = s.top();
s.pop();
if (s.empty()) break;
int left = s.top();
int wid = right-1-left;
int hei = min(height[left], height[right]) - height[top];
ret += wid * hei;
}
s.push(right);
}
return ret;
}
题解三:双指针
int trap(vector<int>& height) {
int left = 0, right = height.size() - 1;
int leftMax = 0, rightMax = 0, ret = 0;
while (left < right) {
leftMax = max(leftMax, height[left]);
rightMax = max(rightMax, height[right]);
if (height[left] < height[right]) {
ret += leftMax - height[left];
++left;
}
else {
ret += rightMax - height[right];
--right;
}
}
return ret;
}
容器最大容量
给定若干木板,选择2根,抽掉其余全部,求最大的容量
int maxArea(vector<int>& height) {
vector<int> &a = height;
int l = 0, r = a.size()-1;
int maxn = -1;
while (l < r) {
maxn = max(maxn, min(a[l], a[r])*(r-l));
if (a[l] < a[r]) ++l;
else --r;
}
return maxn;
}