当青训营遇上码上掘金
本篇文章是参加「青训营 X 码上掘金」主题创作活动的文章作品,选择的主题 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 个单位的青豆。
解题思路
阅读完题目后让人很自然地想到木桶理论,也就是说由多块木板构成的木桶,决定木桶盛水量多少的关键因素是其最短的木板。只不过现实中的木桶是三维的,而我们题目中要处理问题的二维的罢了。顺着这一思路那我们下面要思考的问题无非就两个,一个是存在多少个桶的问题,另一个是如何求桶内的容积的问题,下面将分别讲解。
多少个桶的问题
通过分析我们可以看出题目中的例子应该存在两个桶,如下图所示,那么这两个桶是怎么得到的,我们可以规定这样一个方法,每次取最长的两块木板,这样能构成一个不会漏的桶,然后沿着同一方向再找两块最长的木板,就能得到另一个桶,直到所有木板都被遍历过一遍为止。
在这个问题中可能会遇到两种情况,第一种和例子中的一样,最长的木板在边缘位置,这样去寻找下一个木桶的时候只需要沿着一个方向就好了;第二种就是最长的木板不在边缘位置,这个时候需要我们将左右两个方向分别讨论,变为和第一种情况一样。
桶的容量的问题
当我们划分出桶后,计算桶的容量就非常简单了,以短板为长度计算总容量再减去其中木板所占的容量即可。
func getCapacity(columns []int) int {
n := len(columns)
capacity := n * columns[n-1]
for i, v := range columns {
if i == 0 {
capacity -= columns[n-1]
} else {
capacity -= v
}
}
return capacity
}
递归思路
当我们沿着一个方向去计算每个桶的容量并将它们相加的时候,明显体会到这可以是个递归过程,因此可以编写递归程序:
func resolution(columns []int) int {
capacity := 0
resColumns := make([]int, len(columns) - 1)
copy(resColumns, columns[1:])
nextHighest := highestColumn(resColumns)
if len(columns) <= 1 {
return capacity
}
capacity = getCapacity(columns[:nextHighest + 2])
capacity += resolution(resColumns[nextHighest:])
return capacity
}
完整代码见链接地址:code.juejin.cn/api/raw/719…