攒青豆咯~ | 青训营

46 阅读2分钟

当青训营遇上码上掘金

选择主题:(4)

问题描述

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

image.png

一眼看上去,还以为是什么新奇的题目,新奇的套路,青豆?雨水罢!\doge

问题分析

这是一个典型的接雨水问题,其实这个问题有很多种解答方式,在此我仅解答一种罢。

如何考虑?横向一行一行求还是纵向一列一列求?其实横纵都可以,横向求时间复杂度为:如果最大的数是 m,个数是 n,那么就是 O(m∗n);如果是纵向求,时间复杂度:O(n²),遍历每一列需要 n,找出左边最高和右边最高的墙加起来刚好又是一个 n,所以是 n²。

我们就以上图为例,我需要求某一列青豆数,根据“木桶效应”,我要找到此列左边最高的(优势)和右边最高的(优势),然后比较两个最高的,找出其中较低的那个(木桶效应),那么我求的这一列的青豆数,就是较矮的墙的高度减去当前列的高度。

比如我要求上图显示的第四列的青豆数,第四列的墙高为 1,往左扫描最高为 5,往右扫描最高为 4,两者取较低者 4,然后这一列所能收集的青豆数即 (4 - 1) = 3 个。

所以代码就很简单了,写循环遍历每一列,然后再进行左右扫描遍历,然后进行简单的加减法就可以了。

代码见链接:code.juejin.cn/pen/7196187…

事后再思

其实不难发现,我们不需要每次都左右遍历,可以使用动态规划,能够将时间复杂度降到 O(n)。