当青训营遇上码上掘金之主题 4

128 阅读2分钟

当青训营遇上码上掘金

现有 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 个单位的青豆。

动态规划解法

  • left[i] = max(left[i-1], heights[i])
  • right[i] = max(right[i+1], heights[i])

声明 left 和 right 两个数组,分别表示当前柱子左边和右边的最大高度。 然后用循环将 left[0] 赋值为 height[0], 从 i=1开始,遍历每一个柱子,left[i] 取 max(left[i-1], height[i]),用来更新当前柱子左边的最大高度。 同样的,right[n-1] 赋值为 height[n-1], 从 i=n-2 开始倒着遍历每一个柱子, right[i] 取max(right[i+1], height[i]), 用来更新当前柱子右边的最大高度。 最后,在遍历每一个柱子时,累加 min(left[i], right[i]) - height[i] , 并赋值给 res,最终返回 res 就是最大青豆数量。

时间复杂度为 O(n), 空间复杂度为 O(n)。

双指针解法:

使用两个指针分别从数组的两端开始遍历,并在遍历过程中存储左右两边的最大高度。 通过不断移动指针,累加左右两边高度之差并与当前柱子高度进行比较,最后返回累加值就是最大矩形面积。

将 left 指针设置为 0 , right 指针设置为 n - 1,记录 left_max 和 right_max 为左右两边最大高度,并在 while 循环中进行遍历。

当左指针指向的柱子高度小于右指针时,如果当前柱子高度大于等于 left_max,则更新 left_max, 否则累加 left_max 与当前柱子高度之差。反之,则更新 right_max,累加 right_max 与当前柱子高度之差。

最后返回累加值 res 就是最大青豆数量。

时间复杂度为 O(n),空间复杂度为 O(1)

暴力枚举法

遍历整个数组,对于每一个柱子,找到它左边和右边的最大高度left_max 和 right_max,然后计算左右两边最大高度中较小值与当前柱子高度之差,并累加到结果 res 中。

因为需要枚举每个柱子的左右边界,对于每个柱子需要遍历整个数组,所以总时间复杂度较高。 时间复杂度为 O(n^2),空间复杂度为 O(1)