「青训营 X 码上掘金」主题 4——攒青豆

55 阅读2分钟

当青训营遇上码上掘金

主题介绍

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

image.png

以下为上图例子的解析:

输入:height ={ 6, 0, 3, 1, 2, 0, 1, 0, 4}

输出:17

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

思路解析

根据题目可以得出,能接住多少青豆取决于凹槽两边柱子的高度,并且以矮的柱子为准,该位置能接到的青豆的个数等于矮的柱子的高度减去当前位置的柱子高度。

双指针法,也就是从左到右遍历和从右到左遍历同时进行。

以从左向右遍历数组为例:

遍历从数组下标1开始,因为如果0不是柱子的话也接不到豆子。

  1. i = 1,该位置没有柱子(柱子高为0),左侧最大值为5,右侧最大值为4,所以1位置可以接到4颗青豆。
  2. i = 2,该位置柱子高位2,左侧最大值为5,右侧最大值为4,所以2位置可以接到4 - 2颗,即2颗青豆。
  3. i = 3,该位置柱子高位1,左侧最大值为5,右侧最大值为4,所以2位置可以接到4 - 1颗,即3颗青豆。
  4. i = 4,该位置柱子高位4,左侧最大值为5,右侧没有比4更大的值,所以4位置接不到豆子。
  5. ......
  6. 以此类推,遍历整个数组就可以得出整个数组能接到多少青豆了。

代码实现

能接住多少青豆取决于凹槽两边柱子的高度,并且以矮的柱子为准,该位置能接到的青豆的个数等于矮的柱子的高度减去当前位置的柱子高度。

对数组进行遍历,遍历从左右两侧同时进行。

public class Main {
    public static void main(String[] args) {
        int[] height = { 5, 0, 2, 1, 4, 0, 1, 0, 3};
        int sum = calculate(height);
        System.out.println(sum);
    }

    public static int calculate(int[] arr) {
        int L = 0;
        int R = arr.length - 1;
        int MAX_L = 0;
        int MAX_R = 0;
        int sum = 0;
        while (L < R) {
            if (arr[L] < arr[R]) {
                if (arr[L] >= MAX_L) {
                    MAX_L = arr[L];
                }
                sum += MAX_L - arr[L++];
            } else {
                if (arr[R] >= MAX_R) {
                    MAX_R = arr[R];
                }
                sum += MAX_R - arr[R--];
            }
        }
        return sum;
    }
}
复制代码