双指针解法
前提: 我们需要求一个槽可接水数量,只需要知道其左边的最大高度lmax和右边的最大高度rmax,
因此,根据木桶原理,只要可以接水的量就是 min(lmax, rmax) - height[i]
llm: 左指针的左边最大值
lrm: 左指针的右边最大值
rlm: 右指针的左边最大值
rrm: 右指针的右边最大值
公理: lrm ≥ \ge ≥ rrm, rlm ≥ \ge ≥ llm
if llm
<
<
< rrm then lrm
>
>
> llm => 左指针的两边最小值必为llm
if llm
>
>
> rrm then rlm
>
>
> rrm => 右指针的两边最小值必为rrm
由于维护两个左右指针,因此我们一定知道llm和rrm的值.
class Solution {
public:
int trap(vector<int>& height) {
const int len = height.size();
if(len == 1) return 0;
int l = 0, r = len - 1;
int res = 0;
int lmax = height[0];
int rmax = height[len - 1];
while(l <= r){
if(lmax < rmax){
if(lmax < height[l]){
lmax = std::max(lmax, height[l]);
}else{
res += lmax - height[l];
}
++l;
}else{
if(rmax < height[r]){
rmax = std::max(rmax, height[r]);
}else{
res += abs(height[r] - rmax);
}
--r;
}
}
return res;
}
};
单调栈
像单调栈就比较合适用来求这种,对于某个数来讲,右边或左边,第一个大于它的数。
class Solution {
public:
int GetElem(vector<int>& arr, int n, int idx) {
if (idx == -1 || idx == n) return 0;
return arr[idx];
}
int trap(vector<int>& height) {
const int len = height.size();
if (len == 1) return 0;
stack<int, deque<int>> stk;
int res = 0;
for (int i = -1; i <= len; ++i) {
while (!stk.empty() && GetElem(height, len, stk.top()) < GetElem(height, len, i)) {
int cur = GetElem(height, len, stk.top()); stk.pop();
if (stk.empty())break;
int l = GetElem(height, len, stk.top());
int r = GetElem(height, len, i);
res += (std::min(l, r) - cur) * (i - stk.top() - 1);
}
stk.push(i);
}
return res;
}
};