接雨水
接雨水
题目描述
给定 n
个非负整数表示每个宽度为 1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
1 |
|
示例 2:
1 |
|
提示:
n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105
解题思路
三种思路:
按列思考(纯暴力),思考每一列可以接多少雨水;
具体实现思路,从第二列开始向左找最高的柱子并记录高度tmp_l,并且向右找最高的柱子记录高度tmp_r,记录当前列柱子高度为tmp,那么当前列接雨水的数量ans=min(tmp_l,tmp_r) - tmp;
按行(栈)思考,匹配两个柱子之间所占行的雨水数;
dp优化方法1,定义集合f_l[i]代表第 i 列左边最高的墙的高度,f_r[i]代表第 i列右边最高的墙的高度,构建如上集合后,用法1解。
状态转移方程:
- f_l[i] = max(f_l[i-1], height[i-1])
- f_r[i] = max(f_r[i+1], height[i+1])
堆思路(木桶效应):
我们可以先让两边的端点入堆,然后弹出较小者,并检查其左(或右)的高度是否比它小,如果比它小,说明可以注水,那么,我们就把它注水到相同的高度,并将注水后的高度入堆,如果比它高,直接入堆,依次进行下去,最终,总的注水量就是接雨水的量。
当然,这里为了防止重复访问每个坐标,我们使用一个 si 变量记录已经访问过的坐标。
代码
- 纯暴力
1 |
|
AC记录:
可以看出来,暴力的效率很差。
- 按行思考,考虑用栈来处理,入栈策略为:
- 当前高度小于等于栈顶高度,入栈,指针后移。
- 当前高度大于栈顶高度,出栈,计算出当前墙和栈顶的墙之间水的多少,然后计算当前的高度和新栈的高度的关系,重复当前的步骤。直到当前墙的高度不大于栈顶高度或者栈空,然后把当前墙入栈,指针后移。
代码如下:
1 |
|
AC记录:
这种方法快了很多嘿嘿嘿。
- dp优化方法1
1 |
|
AC记录:
比栈还要快!!!
众所周知,dp可以用滚动数组优化,但是这里有两个dp,我们选择优化其中一个,代码如下:
1 |
|
AC记录:
感觉效率没什么变化。
- 堆:
1 |
|
AC记录:
emm,至此此题结束啦!!!(>.<完结撒花)
接雨水
http://example.com/2023/07/03/接雨水/