题目传送门:
42. 接雨水 - 力扣(LeetCode)https://leetcode.cn/problems/trapping-rain-water/description/这题暴力一下就能过的,还有双指针-对撞指针的优化版本,感兴趣的可以去搜一下
不是我原创的写法我就不讲了
但是会在后面贴一份这个代码
这里介绍一种双指针-滑动窗口的写法
思路:
每轮操作找一个 "凹陷处",并统计。"凹陷处" 找法:
先找凹陷处左侧最高点,若满足 i < 边界 && 单调不降,则 i++
再找凹陷处右侧最高点,j 初始化为 i+1,若满足 j < 边界 && arr[j] < arr[i],则 j++
且在 j++ 之前,ret += arr[i] - arr[j]
一轮凹陷处找完后,i 更新为 j,继续向右进行下一轮操作
为保证凹陷处右侧最高点不低于凹陷处左侧最高点,需要找到全局最高点
然后从两侧依次向中间进行上述操作即可。换方向后 ++、< 等有方向性的操作符,记得改一下
代码:
class Solution
{
public:
int trap(vector<int>& height)
{
int ret = 0, mx = 0;
for (int i = 0; i < height.size(); i++) if (height[i] > height[mx]) mx = i;
for (int i = 0, j = 0; i < mx && j < mx; i = j)
{
while (i < mx && height[i] <= height[i + 1]) i++;
j = i + 1;
while (j < mx && height[j] < height[i]) ret += height[i] - height[j], j++;
}
for (int i = height.size() - 1, j = height.size() - 1; i > mx && j > mx; i = j)
{
while (i > mx && height[i] <= height[i - 1]) i--;
j = i - 1;
while (j > mx && height[j] < height[i]) ret += height[i] - height[j], j--;
}
return ret;
}
};
看起来有点多,实际上后两个 for 循环干的事是一样的,思考出其中一个就可以了
对撞指针代码:
class Solution
{
public:
int trap(vector<int>& height)
{
int lmax = 0, rmax = 0, ret = 0;
for (int l = 1, r = height.size() - 2; l <= r;)
{
if (height[l - 1] > lmax) lmax = height[l - 1];
if (height[r + 1] > rmax) rmax = height[r + 1];
if (lmax <= rmax && l <= r) ret += max(0, min(lmax, rmax) - height[l]), l++;
if (lmax >= rmax && r >= l) ret += max(0, min(lmax, rmax) - height[r]), r--;
}
return ret;
}
};