当青训营遇上码上掘金

79 阅读2分钟

当青训营遇上码上掘金

主题 4:攒青豆

题目描述

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

(这个题和力扣某个题高度相似)

思路

考虑每一列,我们发现这一列装水的容量不仅取决于自己的高度(自己太高了突出去肯定没法接),也取决于自己周围的高度(两边低了也不行)

具体来看一个例子

image.png

考虑a柱子,它能接的容量取决于自己高度2,左边最高的5,右边最高的4,具体为min(maxLeft,maxRight)-curH=min(5,4)-2=4-2=2

同理,考虑b柱子,它能接的容量取决于自己高度1,左边最高的5(这里看高度为5的那个,而不是4),右边最高的3,具体为min(maxLeft,maxRight)-curH=min(5,3)-1=3-1=2

因此我们思路明确了,对于每一个柱子,它的容量等于min(两侧最大值)减去自己高度,即min(maxLeft,maxRight)-curH;如果自己比两侧最值还要大,说明凸出去了,就像图中的高度5一样,这时候它的容量是0

实现

方法1

最暴力的想法,对于每一根柱子,枚举两侧的最大值和最小值,代入表达式计算即可 时间复杂度,遍历每一个O柱子(n),对于每一个柱子需要遍历全部来求出最大值和最小值同样需要O(n) 总的时间复杂度O(n*n)

如何优化? 注意到每个柱子求左右最值的时候会重复遍历很多次数组,可不可以优化呢?

方法2

使用动态规划来对求最值的过程进行优化

maxL[i]代表考虑到第i个元素时,左侧的最值(不包含自己); maxL[i]=max(maxL[i-1],h[i-1]);

maxR[i]代表考虑到第i个元素时,右侧的最值(不包含自己); maxR[i]=max(maxR[i+1],h[i+1]);

这样预处理,就可以优化掉求最值的时间复杂度,总的时间复杂度为O(n)

还可以继续优化空间复杂度,供思考