当青训营遇上码上掘金
主题四:攒青豆
题干:现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
方法一:暴力求解
思路:
- 可以统计每个位置上的青豆数量
- 各个位置的青豆数量为左右最高柱子中较小的减去该位置的柱子高度
- 因为每到一个位置都要对左右两边进行一次遍历相当于循环嵌套了一层分析左右两边最高位置的循环,所以其复杂度是O(n^2)。
可能的改进方向:可以看到我们计算每个位置上能积累的青豆数总共需要三个信息:1.该位置左边的最高柱子;2.该位置右边的最高柱子;3.该位置的柱子高度 3是已知的,我们只需要先双方向遍历两次找到1和2即可 代码过程: 略,看到这一步时已经有能够显著加速的方法了
方法二:双方向遍历
思路:
- 有个更直观的思考角度,假设以最高高度为基准,先将青豆填满,之后青豆会流走。
- 青豆流走取决于左右两边最高柱子的较小值,所以我们获得两个数组left_height和right_height,分别代表从左到右的最高值,从右到左的最高值。
- 最后青豆等于各个位置:min(left_height - right_height) - height
举例: 输入:height = [5,0,2,1,4,0,1,0,3]
两次遍历后得到:
height = [5,0,2,1,4,0,1,0,3]
left_height = [5,5,5,5,5,5,5,5,5]
right_height = [5,4,4,4,4,3,3,3,3]
bean_sum = (5-5)+(4-0)+(4-2)+(4-1)+(4-4)+(3-0)+(3-1)+(3-0)+(3-3) = 17
python完整代码:
个人感想
之前也有遇到过类似的题目,感觉先从不管数据要求,先从暴力求解的角度入手,再从原理中寻找改良的可能,这样的思路会是我面对较复杂题目的一个思考模式。虽然我青训营实际上是前端的,但一想到这次攒青豆的青训营规则就还是选择了主题四,只能说算分我是擅长的。