给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 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 个单位的雨水(蓝色部分表示雨水)。
示例 2:
**输入:**height = [4,2,0,3,2,5]
**输出:**9
提示:
n == height.length
1 <= n <= 2 * 10(4)
0 <= height[i] <= 10(5)
每次只有遇到比前面高的方块时才需要更新ans,所以考虑使用单调栈
单调递减,栈顶小于当前元素时弹出,然后更新ans,更新时注意比较前一个元素与当前元素,取较小的值作为高
因为矮的元素会被弹出,所以我们必须记录下标索引,这样后面遇到高元素时才能同时考虑矮元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Solution { public : int trap(vector<int> &height) { stack<int> s; int len = height.size(); int ans = 0; for (int i = 0; i < len; i++) { while (!s.empty() && height[s.top()] < height[i]) { int last = s.top(); s.pop();
if (s.empty()) break;
int left = s.top(); int w = i - left - 1; int h = min(height[left], height[i]) - height[last]; ans += w * h; } s.push(i); } return ans; } };
|
针对每个柱子分析,我们可以把所有柱子上的水加一起,
想知道每个柱子上有多少水,我们需要知道这根柱子左边最高多少,右边最高多少,然后取min减去当前即可
两次遍历分别获得向左向右看最高的柱子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public: int trap(vector<int>& height) { int len = height.size(); if (len <= 1) return 0;
vector<int> left_max(len); left_max[0] = height[0]; for (int i = 1; i < len; i++) left_max[i] = max(left_max[i - 1], height[i]);
vector<int> right_max(len); right_max[len - 1] = height[len - 1]; for (int i = len - 2; i >= 0; i--) right_max[i] = max(right_max[i + 1], height[i]);
int ans = 0; for (int i = 0; i < len; i++) ans += min(left_max[i], right_max[i]) - height[i]; return ans; } };
|
根据上述发现,每个柱子上的水只与左右较小的柱子有关,而且柱子本身也参与左右最高柱子的比较
我们可以用双指针l,r从两头向中间靠拢
当 height[l]<=height[r] 时,隐含了 l 处向右看最高值一定大于等于 height[l],此时我们只要看 left_max 就能计算出 left 位置的水量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: int trap(vector<int>& height) { int len = height.size(); int l = 0, r = len - 1; int left_max = 0, right_max = 0; int ans = 0; while (l < r) { left_max = max(left_max, height[l]); right_max = max(right_max, height[r]); if (height[l] <= height[r]) { ans += left_max - height[l]; l++; } else { ans += right_max - height[r]; r--; } } return ans; } };
|