主题4:攒青豆问题
1.问题描述:现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。
解题思路:
首先,要想豆子能够装到柱子间,那肯定是需要一个凹起来的形状,那么如果将这些柱子的高度看成是顶点,再用光滑线条连接起来,其实就是一条曲线。所以计算接到的豆子,就是得首先找到能接住这些豆子的一些区间,再将这些区间能构成的面积加起来,就是结果。
1.在数学上,我们学过局部极小值,也就是在一个限定区间内,最在一个值比它两边的任何一个值都要小。所以,我们就是需要接下来找到这样的极小值存在的一个区间。
2.那么这里方便记录区间两边的数值边界情况,因此采用双指针的方法。数组的元素值看作木板的高度,也就是局部区间的边界大小,举个例子,若最左边的边界感度为1,与它相邻右边的高度如果不低于它,是装不到任何东西的,所以,这里需要一个值记录一下当前局部最大的边界值,当有更高的边界值出现在其右边时,就更新当前局部变量最大值这个变量,这里的话,对于右边的边界,也是一样的情况,需要另外一个值记录一下当前局部最大的右边界值,当有更高的边界值出现在其左边时,就更新当前局部变量最大值这个变量,否则,就计算这个高度差,这个高度差就是每一次移动边界指针时能装下青豆的数量,那么有人会问,之前说不是计算面积吗,面积是长乘以宽,这里让高度差Hight作为长,那宽度是多少呢,其实宽度的话就是1,因为每次左右指针移动的单位就是1,所以每移动一次的面积计算,就是高度Hight * 1,也就是只需要累加这个高度差Hight即可。
3.整体流程,让左指针往右移动,右指针往左移动,再用两个变量记录临时的局部边界高度即可,再遍历元素的过程中,如果左指针所在的边界高度大于右指针,这时候可以让左指针停下来了,然后去移动右指针,那么终止条件就是这两个指针相遇,最终累加的高度差之和就是最终的答案。