当青训营遇上码上掘金
题目描述
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
问题分析
针对上述问题,我们先手动构造几份案例,然后对问题展开分析!
样例1:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
复制代码
方法
该问题,考察了双指针算法、栈、动态规划等多种解题思路。
解法1:暴力求解 对于每个柱子,向左和向右扫描,找到它左右两侧最高的柱子。当前柱子能够容纳的青豆数量即为其左右两侧最高柱子中的较小值与当前柱子高度之差。
该方法的时间复杂度为O(n^2),空间复杂度为O(1)。
解法2:双指针算法 为了优化时间复杂度,可以使用双指针算法。左右指针分别指向柱子的最左和最右端,同时维护左右两侧的最高柱子高度。如果当前左指针指向的柱子高度小于等于右指针指向的柱子高度,从左侧计算;否则,从右侧计算。每次计算完一侧后,指针向中间移动,直到左右指针相遇。
该方法的时间复杂度为O(n),空间复杂度为O(1)。
解法3:栈 栈可以用来保存还没有找到右侧边界的左侧柱子。遍历所有柱子时,如果当前柱子的高度小于栈顶柱子的高度,将其加入栈中;否则,从栈中弹出所有小于当前柱子高度的柱子,并计算它们能够接到的青豆数量。每个弹出的柱子,都可以认为是能够接到青豆的空洞。当栈为空时,遍历结束。
该方法的时间复杂度为O(n),空间复杂度为O(n)。
解法4:动态规划 使用动态规划,需要先计算每个柱子左右两侧的最高柱子高度,然后遍历所有柱子,计算当前柱子能够接到的青豆数量。某个柱子能够接到的青豆数量,即为该柱子左右两侧最高柱子高度中的较小值与当前柱子高度之差。
该方法的时间复杂度为O(n),空间复杂度为O(n)。
代码
代码片中的js代码,也就是trap函数,只需我们将柱子的高度给他,便可以得到具体可以攒到多少个豆子。已经封装完整。
总结
总体而言,双指针算法是最优解,该方法的时间复杂度为O(n),空间复杂度为O(1)。