题目

思路
看了很久没思路,直接参考了网上的题解。
思路大概就是维护一个单调栈,其中存储的是每个块的下标,当有一个没找到比他更高的右边块时将其入栈(只要是没有更高的右方块就入栈,所以栈中会存放不止一个块,其中高度是非递增的),直到有一个更高的右方块出现,就把当前栈顶出栈,作为坑底,将当前栈顶(已经出栈的坑底的左边一个块)作为左边界,左右边界的更低者减去坑底高度为存储水位,宽度为右边界减去左边界,水量就是水位*宽度。
注意这样算的话是按每一层横向来算的。
代码
cpp
class Solution {
public:
int trap(vector<int>& height) {
stack<int> st; // 存数组下标的单调栈(从底到顶高度单调递减)
int total_water = 0;
for (int i = 0; i < height.size(); i++) {
// 当前柱子如果比栈顶柱子高,说明找到了栈顶柱子的"右边界高墙"
while (!st.empty() && height[i] > height[st.top()]) {
int bottom_index = st.top(); // 获取坑底的下标
st.pop(); // 坑底出栈
// 如果栈空了,说明左边没有高墙了,像是一个左边漏水的悬崖,接不住水,直接退出循环
if (st.empty()) {
break;
}
// 此时新的栈顶就是坑底左边的高墙
int left_index = st.top();
int right_index = i;
// 积水的宽度
int w = right_index - left_index - 1;
// 积水的高度 = 左右两墙的较矮者 - 坑底的高度
int h = min(height[left_index], height[right_index]) - height[bottom_index];
// 累加这一个横向层面的雨水量
total_water += w * h;
}
// 当前柱子入栈,等待后面比它高的柱子来和它形成凹槽
st.push(i);
}
return total_water;
}
};
结果
