当青训营遇上码上掘金
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入: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)