当青训营遇上码上掘金

62 阅读1分钟

青训营x码上掘金

主题4:攒青豆

一、问题描述

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

screenshot-20230213-163258.png

二、解题思路

首先将最左端和最右端设置为两端最大高度,然后从左端第二个和右端第二个位置开始往中间遍历,直到相遇为止。 在遍历数组过程中优先处理最大高度小的一端,然后比较当前端此时的最大高度值和此时遍历到的高度值,如果小于等于最大高度值,则将差值累加到结果中;若大于高度值,则更新当前端最大高度。最后将结果返回即为攒的青豆数量。该算法遍历了一遍数组并且用到了5个变量,所以时间复杂度为O(N),空间复杂度为O(1)。

三、代码


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

    private static int zanQingDou(int[] nums) {
        int leftMax = nums[0];   // 左边当前最大高度
        int rightMax = nums[nums.length - 1];   // 右端当前最大高度
        int L = 1;   // 从左到右遍历到的位置
        int R = nums.length - 2;   // 从右到左遍历到的位置
        int res = 0;  
        while(L <= R){
          // 优先处理当前最大高度小的一端
          if(leftMax <= rightMax){
            res += Math.max(leftMax - nums[L], 0);   // 累加青豆数量
            leftMax = Math.max(leftMax, nums[L]);    // 更新左端最大高度
            ++L;
          }else{
            res += Math.max(rightMax - nums[R], 0);   // 累加青豆数量
            rightMax = Math.max(rightMax, nums[R]);   // 更新右端端最大高度
            --R;
          }
        }
        return res;
    }
}