「青训营 X 码上掘金」主题4-攒青豆

52 阅读2分钟

主题4: 攒青豆

现有n个宽度为1的柱子,给出 n个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

image.png

测试案例如下:

以下为上图例子的解析:

输入:height = [5,0,2,1,4,0,1,0,3]  
输出:17  
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。

通过分析我们题目要求我们很容易分析出对于下标 i ,青豆能到达的最大高度等于下标 i 两边的最大高度的最小值,下标i处能到达的最大高度减去height[i]。

所以本题的暴力解法是:遍历height数组中的每个元素,分别向左向右扫描同时记录左边和右边的最大高度,然后计算每个下标位置能攒到的青豆数。本题数组height长度为n,该做法需要在下标i处向两边扫描最大值,所以时间复杂度是O(n^2)。

当然我们可以通过动态优化来预处理数据,通过O(n)的时间复杂度首先将每个位置左右两边的高度记录下来,再进行计算最终能够攒的青豆个数。最后分析时间复杂度,经过了三次时间复杂度O(n)的遍历,所以最终时间复杂度为O(n)。

base cese:
leftMax[0] = height[0]
rightMax[n - 1] = height[n - 1]
其他情况:
1 <= i < n - 1时,leftMax[i] = max(leftMax[i - 1], height[i])
0 <= i < n - 2时,rightMax[i] = max(rightMax[i + 1], height[i])

通过上述状态转移方程,所以我们需要正向遍历height得到leftMax数组,通过方向遍历height得到rightMax数组,在得到两个leftMax和rightMax的值之后,对于下标i位置能攒到的青豆数:
bean[i] = min(leftMax[i],rightMax[i]) - height[i]

具体代码详见: code.juejin.cn/pen/7194731…