当青训营遇上码上掘金----精打细算的攒青豆

86 阅读2分钟

题目描述

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

725ef710a59944d49d0315bece7a1ac1~tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0[1].awebp

问题分析

针对上述问题,我们先手动构造几份案例,然后对问题展开分析!

样例1:

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

样例2:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的柱子高度,在这种情况下,可以接 6 个单位的青豆。

思路: 双指针解法:

  • 如果后面的存在比当前柱子高的,那么就用那个高的柱子作为right, 把当前柱子的高度作为height,然后遍历 left -> right 挨个计算可以接的青豆。

  • 当后面的柱子都比left柱子低,那么就要在 left -> length-1之间找一个最高的柱子maxHeight,然后,从left+1 -> max开始遍历,挨个计算可以接的青豆。

动态规划解法:

这并不是一道典型的动态规划题,但是动态规划的思想是可以应用的。难想的点在于初始化状态。

  • 首先,我们需要找到所有左边最高的柱子和右边最高的柱子。我们可以使用两个数组leftMax和rightMax来存储,其中leftMax[i]代表第i个位置左边最高的柱子,rightMax[i]代表第i个位置右边最高的柱子。然后就可以根据这两个数组递推啦!
  • 然后,我们需要找到每个位置的最大容量。对于第i个位置,它的最大容量就是min(leftMax[i], rightMax[i]) - columns[i]。
  • 最后,我们可以将每个位置的最大容量相加,得到总的容量。

AC代码

代码片中的js代码,也就是trap函数,只需我们将柱子的高度给他,便可以得到具体可以攒到多少个豆子。已经封装完整。

总结

其实除了双指针法,还有一些其他的方法可以解出这个题目。 例如:

  • 暴力法
  • 栈模拟
  • 动态规划
  • 贪心算法

总的来说几种方法运行速率对比如下:

491959
暴力法运行时间:449046
491959
栈模拟法运行时间:1323
491959
双指针运行时间:93
491959
动态规划运行时间:261
491959
贪心法运行时间:92