主题 4:攒青豆题解 | 青训营活动

85 阅读2分钟

当青训营遇上码上掘金

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

攒青豆.png

以下为上图例子的解析:

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

问题分析:

单从每一列青豆数量角度考虑,它的高度取决于它左右最高柱子中较小的那个,那么它的青豆数量就等于总高度减去黑柱高度的结果(结果必须大于零)。对每一列进行相同计算就可统计出总青豆数。

时间复杂度分析:

单列柱子在寻找左右最高柱子时查找左右的最大值,查询需要O(n),
那么n列时间复杂度为O(n)

代码分析:

先定义两个变量来记录左右两端的最大值,从左右两端向中间遍历。如果左右指针指向的值大于对应的最大值,则更新最大值为当前值,否则,计算青豆数量,当左右两个指针为同一位置时,结束循环, 最后将返回青豆总数量。

public static int qingdou(int[] arr) {
        int left = 0;
        int right = arr.length - 1;
        int MAX_L = 0;
        int MAX_R = 0;
        int sum = 0;
        while (left < right) {
            if (arr[left] < arr[right]) {
                if (arr[left] >= MAX_L) {
                    MAX_L = arr[left];
                }
                sum += MAX_L - arr[left++];
            } else {
                if (arr[right] >= MAX_R) {
                    MAX_R = arr[right];
                }
                sum += MAX_R - arr[right--];
            }
        }
        return sum;
    }
    

完整的代码已放到码上掘金上。

从单列角度分析清晰易懂,当然还有很多其他方法等待大家去发现~