当青训营遇上码上掘金-攒青豆-主题4

86 阅读2分钟

当青训营遇上码上掘金

题目描述

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

image.png

以下为上图例子的解析: 输入: height = [5,0,2,1,4,0,1,0,3]

输出:17

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

题目分析

攒青豆这道题目是给你一个整数数组,这些整数表示柱子的高度, 而柱子之间所包围的区域是可以接青豆的, 问当前数组一共能接多少个青豆,如这个数组我们一个接了17个单位的青豆。

本题采用一个双指针的解法。

首先我们用lMax代表左边的最大高度,rMax代表右边的最大高度。

  1. 对于某一个位置i来说,能否接住雨水,取决于它左右两侧的最大值(lMax, rMax)是否都大于height[i].只有当左右两侧都大于height[i]时,才能接住雨水,数量为min(lMax, rMax) - height[i].这得出结论,限制当前位置接雨水的条件是其左右两侧最大值中的较小值min(lMax, rMax). 对于i和j两个指针,i从左向右移动,j从右向左移动。
  2. 对于指针i来说,lMax是真实可信的,但是rightMax是不真实不可信的,因为i不知道从height[i]到height[j]之间是否有其他数大于rMax。同样,对于j来说rMax是真实可信的,lMax值是不真实不可信的。这得出结论:对于左指针i,它右侧的真实最大值 >= rMax,对于右指针j,它左侧的真实最大值 >= lMax.
  3. 基于点1,我们知道对于一个位置来说影响它接水的应该是左右两侧最大值中的较小值min(lMax, rMax).而基于点2,我们知道左指针右侧的真实最大值会大于等于rMax.所以当出现lMax < rMax时,左指针的位置是否能接雨水就已经确定了,同样,当出现lMax >= rMax时,右指针的位置是否能接雨水也已经确定了。因此,我们可以根据这些要点写出代码来解决问题。

代码

时间复杂度O(n)