当青训营遇上码上掘金~
题目描述
先来看一下题目描述:
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
具体解法
解法一:暴力法
以下图箭头所指的位置为例,这个位置能装下多少青豆?
显然,这个位置能装的青豆数,取决于它两侧的比它高的柱子中最高的两根中的矮的那根,这句话听起来比较拗口,简单来说,左边最高的是5,右边是4,所以能装的青豆高度取决于这两根最高的柱子中矮的那根,即4,所以能装4个单位的青豆。但是这个位置的柱子高度为1,还要减去这个高度,所以最终能装4-1个青豆。
用代码描述为:
nums[i] = min( max(height[0:i]), max(height[i:n-1]) ) - height[i]
据此,我们可以写出如下的暴力算法:
这个算法的时间复杂度是O(N^2),空间复杂度O(1)。
备忘录法
由于每个位置都要计算l_max和r_max,时间复杂度就很高。
我们可以开两个数组r_max和l_max,l_max[i]表示height[0:i]中最高柱子的高度。
这是一个典型的以空间换时间的解法,时间复杂度降为O(N),空间复杂度O(N)。
双指针法——最优解
用双指针边走边算。
双指针法的时间复杂度是O(N),空间复杂度O(1)。