接青豆 |「青训营 X 码上掘金」

52 阅读2分钟

当青训营遇上码上掘金

序言

本文记录和整理了本人在字节青训营中学习的一些所得所想,用于本人回顾和梳理相关知识点,也欢迎大家参考,一同学习。如果发现有问题或者错误,可以在下方留言或者私信我(^-^

题目

主题 4:攒青豆

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

image.png

示例

以下为上图例子的解析:

  • 输入:height = [5,0,2,1,4,0,1,0,3]

  • 输出:17

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

思路

最容易想到的思路就是找到每个位置的最大青豆数量,然后累加。

想要接住青豆,那么其几何形状应该是凹下去的,每个位置的最大青豆数量依赖于其左侧 lmaxlmax 和右侧的高度rmaxrmaxlmaxlmax 表示当前位置左侧的最大高度, rmaxrmax 表示当前位置右侧的最大高度,lmaxlmaxrmaxrmax都可以通过一次遍历来获取。但遍历方向不同,lmaxlmax 通过正序遍历,rmaxrmax 通过反向遍历。

lmax[i]=max(lmax[i1],height[i1])lmax[i] = max(lmax[i - 1], height[i - 1])
rmax[i]=max(rmax[i+1],height[i1])rmax[i] = max(rmax[i + 1], height[i - 1])

知道lmaxlmaxrmaxrmax后,就可以很轻松的求出当前位置的能接住的最大青豆数量。

res[i]=min(lmax[i],rmax[i])height[i]res[i] = min(lmax[i], rmax[i]) - height[i]

复杂度分析

  • 时间复杂度:O(n)O(n)nn为数组heightheight的长度,总共需要3次遍历。

  • 空间复杂度:O(n)O(n)nn为数组heightheight的长度,需要创建两个长度为 n+2 的辅助数组 lmaxlmaxrmaxrmax

代码

码上掘金链接:code.juejin.cn/pen/7198342…

public class Main {
    public static void main(String []args) {
        System.out.println("Hello world!");
        int[] height = {5,0,2,1,4,0,1,0,3};
        Main main = new Main();
        int res = main.trap(height);
        System.out.println(res);
    }

    public int trap(int[] height) {
        int res = 0, n = height.length;
        int[] lmax = new int[n + 2];
        int[] rmax = new int[n + 2];

        // 记录左侧最高点
        // lmax[i] == max {h[0] ~ h[i-1]}
        lmax[0] = 0;
        for(int i = 1; i < n; i ++) {
            lmax[i] = Math.max(lmax[i - 1], height[i - 1]); 
        }

        // 记录右侧最高点
        // lmax[i] == max {h[i+1] ~ h[len-1]}
        rmax[n-1] = 0; 
        for(int i = n - 2; i >= 0; i --) {
            rmax[i] = Math.max(rmax[i + 1], height[i + 1]); 
        }

        for (int i = 0; i < n; i++) {
            res += Math.max(Math.min(lmax[i], rmax[i]) - height[i], 0);
        }
        return res;
    }
}