当青训营遇上码上掘金
题目
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
思路
这是一个传统算法题——接雨水问题,只需要我们把每一列的共同特点找出来,也就是先求解对于其中任意一列而言如何求解它能接多少高度的青豆。一列青豆最大的高度是它两边的高度的最小值,而实际接的青豆量就是最大高度减播撒的高度。所以可以先对于每一列分别向左、向右扫描得到的最大高度,但是这种方法有太多重复的地方,每一列都扫一遍全程就是单次O(n),总体复杂度O(n^2)了。所以我们可以据此想到用动态规划来优化一下它:如果预处理已知每个位置左边、右边的最大高度,那么就不需要每一遍都扫描了,因此创建了两个数组lMax和rMax来记录每一列及其后面的位置中能到达的单侧最大高度。因此就有
lMax[0]=high[0],rMax[n-1]=high[n-1]
其余元素则有:当1 <= i <= n 时,lMax = max(lMax[i-1],high[i])
当0 <= i <= n-2 时,rMax = max(rMax[i+1],high[i])
min(lMax[i],rMax[i]) - high[i]
所以我们从0到n,将每列的结果相加即为最终所得了。