当青训营遇上码上掘金。
主题4:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
思路
尝试进行作图,找出可能出现的各种情况。
按列来看,每一列能接住的高度可以不断向上增长,直到与它两侧各自最高的柱子中较低的那个相平为止。
从图上看,可以从较低的一侧向另一侧作水平线,水平线以下的部分就是能接住的部分。
为了得出每一列的高度上限,可以使用两个指针分别从两端出发,每次取较低的那个向内侧作水平线,计算经过的每一列的结果,直到遇到高度相等或更高的柱子而停止。移动指针后继续进行,直到两个指针相遇,即可得出最终结果。
这种算法,每一列只会计算一次,所以时间复杂度是O(N)。只需要存储所有柱子的高度和几个临时变量,所以空间复杂度也是O(N)。
代码
根据思路,使用Go语言编写代码。 height为输入柱子高度的数组,i和j分别为左右两端的指针,k为作水平线时移动的指针,a为计算结果。
左右两端指针未相遇即继续循环。每次循环比较两个指针处的高度,从较低的那个向内作水平线,依次计算经过的每一列的结果,并累加到最终结果上,直到遇到相等或高于水平线的柱子而停止,然后指针移到该处,完成本次循环。
最后循环结束,输出最终结果。