题目:
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
解题思路:
- 首先构建两个栈,
h
存高度,idx
存下标。 - 遍历数组,将
height[i]
与h.top()
做比较- 若
height[i] <= h.top()
,则将对应的高度和下标都入栈。 - 若
height[i] > h.top()
,则表明可能可以求得面积。实际上,对于
index = k
的方块而言,可能接住的雨水等于 min(left, right) * widthleft 表示左边第一个比它高的柱子高度,right表示右边第一个比它高的柱子高度。
width表示宽度。
- 之所以是可能可求得面积,是因为可求面积的重要条件是,左右两边都有柱子。
而恰如题目给出的例子中,
[1, 2]
这样的情况下,index = 1的那个柱子是没办法接雨水的。因为没左边的柱子。这样的情况需要特殊判断。
- 若
- 在求面积的时候,要一直退栈退到栈顶元素比
height[i]
大或者相等
class Solution {
public:
int trap(vector<int>& height) {
stack<int> h, idx;
int sum = 0, tag = 0;
int len = height.size();
for(int i = 0; i < len; i++) {
// 遍历到比栈尾还小的元素时,推入栈中
if(h.empty() || h.top() >= height[i]) {
h.push(height[i]);
tag = 0;
idx.push(i);
continue;
}
while(h.top() < height[i]) {
int temp = h.top();
h.pop(), idx.pop();
if(!h.empty()) {
int left = h.top(), left_h = idx.top();
sum += (min(height[i], left) - temp) * (i - left_h - 1);
} else {
h.push(height[i]);
idx.push(i);
tag = 1;
}
}
// 栈顶只可能比当前height[i]更大或相等
while(!h.empty() && tag == 0) {
if(h.top() == height[i]) {
h.pop(), idx.pop();
if(h.empty()) {
h.push(height[i]);
idx.push(i);
break;
}
} else {
h.push(height[i]);
idx.push(i);
break;
}
}
}
return sum;
}
};
心得:
虽然今天心情烦躁,但是鉴于抓住了一点思路,就打算自己写写这题。
因为之前看了不少关于单调队列、滑动窗口类型的题,感觉它们有点异曲同工的味道,很想尝试。
接近三个小时都在接雨水,提交了4次,最后AC打败了94%,美滋滋。
写着写着就没啥思路了,画图倒是一把好手!
继续跪谢阎总带我算法入门,三四百没白交。
原文地址:https://www.cnblogs.com/recoverableTi/p/12631619.html
时间: 2024-10-16 10:58:21