力扣题解系列:42:接雨水

题目:42. 接雨水

题目描述:

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
来源:https://leetcode-cn.com/problems/trapping-rain-water/

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

思路:(反正我一个都没想出来)

方法一:暴力
核心就是找到每一个矩形上方能够装多少水,那么对于任意一个矩形,怎么算它上方装的水呢?根据木桶效应可以知道是由它两边最高的矩形决定的:具体的思路看图
在这里插入图片描述
这样遍历一遍列表,分别找到每个元素的left_max和right_max,计算每个矩形承载的水量,求和即可,时间复杂度为O(n^2),实测不能AC。
方法二:动态编程(官方题解这么叫)
是对暴力法的改进,典型的空间换时间,既然每个元素都要计算left_max和right_max,那么就
两个数组left_max和right_max分别记录每个元素左边和右边的最大值。然后根据这两个数组,计算每个矩形承载的水量,相当于把原数组遍历了三次,时间复杂度为O(n)。
方法三:单调栈
注意栈里面存放的是元素的序号,然后递减是按照元素大小来比较的。单调递减栈,主要思想就,遍历到元素i时,如果height[i]大于栈顶元素,把栈顶元素当作盛水的底,来计算栈顶元素的盛水量。如下图:
单调栈
弹出栈顶元素并处理完成之后,继续比较栈顶和当前元素的大小,如下图:
在这里插入图片描述
还有一个要注意的点就是,弹出栈顶之后,要判断栈是否为空,栈为空则退出循环。因为弹出栈顶后若栈为空,相当于只有底边和右边,左边没有,存不住水,如下图所示:
在这里插入图片描述
方法四:双指针
核心还是计算每个矩形上方能够承载的水量。动态编程使用两个数组来记录每个元素左边的最大值和右边的最大值,这里进一步优化,只使用两个数来记录。
当左边最大值大于右边最大值时,左边不动,右指针向左遍历,遇到比右边最大值还要大的就更新右边最大值,遇到比右边最大值小的,相当于左边最大值、右边最大值和遍历到的值三者形成了凹陷,可以储水,y因为是在left_max > right_max的条件下,故储水量用right_max-height[i]计算即可。left_max < right的情况同理,不再赘述。
说的不是明白,详细解释都在代码里了,show you the code.

代码:

(1)暴力法:

class 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值