leetcode 42. 接雨水
题目详情
题目链接
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
- 示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
我的代码
class Solution {
public:
int trap(vector<int>& height) {
int len = height.size();
if ((len == 0) || (len == 1) || (len == 2)) {
return 0;
}
int high = height[0], small = height[0];
for (int h: height) {
high = max(high, h);
small = min(small, h);
}
int res = 0;
int start = 0, end = len - 1, last = 0;
for (int h = small + 1; h <= high; ++h) {
for ( ; start < len; ++start) {
if (height[start] >= h) {
break;
}
}
for ( ; end > 0; --end) {
if (height[end] >= h) {
break;
}
}
if (start + 1 > end) {
break;
}
h = min(height[start], height[end]);
for (int i = start + 1; i < end; ++i) {
if (height[i] < h) {
res += (h - max(last, height[i]));
}
}
last = h;
}
return res;
}
};
我的成绩
执行结果:通过
执行用时 : 4 ms, 在所有 C++ 提交中击败了94.78%的用户
内存消耗 : 6.7 MB, 在所有 C++ 提交中击败了100.00%的用户
一些想法
- 已经踩了两个坑,首先需要知道需要接到雨水的柱子不一定是右边要比左边长。
- 今天终于独立完成了这道题,而且看起来成绩还不错。谈谈我的思路,我最开始的想法是先找到最高的柱子和最低的柱子,然后从最低柱子的高度向上加作为h,然后从两边找到大于这个高度的柱子作为边界,然后开始遍历这个边界,这个范围内有小于h的就说明有空格,加1,但最后发现超过了限制时间,说明1个1个往上加有些繁琐,我们可以批量改变h,需要注意的是 res += (h - max(last, height[i]))。
执行用时为 0 ms 的范例
class Solution {
public:
int trap(vector<int>& height) {
if(height.size()<3) return 0;
int n = height.size(), ans = 0;
vector<int> lm(n, height[0]), rm(n, height.back());
for(int i=1; i<n; i++) lm[i] = max(lm[i-1], height[i]);
for(int i=n-2; i>=0; i--) rm[i] = max(rm[i+1], height[i]);
for(int i=1; i<n-1; i++)
ans += min(lm[i], rm[i])-height[i];
return ans;
}
};
思考
范例没看懂,有时间可以看下官方解法。