当青训营遇上码上掘金----主题 4:攒青豆

42 阅读2分钟

当青训营遇上码上掘金

题目描述

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

image.png

以下为上图例子的解析:

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

题目分析

本题与leetcode经典问题接雨水十分相似,leetcode.cn/problems/tr…

我选择采用单调栈的方法来解决这道题,类似于雨水,在本题中,只要柱子高度是递减的,那么当它一旦遇到递增的就可以计算积攒的青豆,利用这个思路,我们可以使用递减栈的思想来计算。

思路详解:

遍历height数组,将其中的元素加入单调递减栈。当栈顶柱子的高度大于当前柱子时,栈里面添加当前柱子;反之如果当前柱子的高度大于栈顶柱子的高度,不断出栈,相当于找到左边比当前柱子矮的位置,然后每次出栈后结算青豆面积并累加。

复杂度分析:

时间复杂度O(n),n是height的长度,数组中的每个元素最多入栈出栈一次。

空间复杂度O(n),栈的空间,最多不会超过height的长度。

代码

import java.util.*;

public class Main {
   public static void main(String []args) {
      int[] height = {5, 0, 2, 1, 4, 0, 1, 0, 3};
      System.out.println(bean(height));
   }
   public int bean(int[] height) {
        int n = height.length;
        if (n == 0) {
            return 0;
        }
        int[] leftMax = new int[n];
        leftMax[0] = height[0];
        for (int i = 1; i < n; ++i) {
            leftMax[i] = Math.max(leftMax[i - 1], height[i]);
        }
        int[] rightMax = new int[n];
        rightMax[n - 1] = height[n - 1];
        for (int i = n - 2; i >= 0; --i) {
            rightMax[i] = Math.max(rightMax[i + 1], height[i]);
        }
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans += Math.min(leftMax[i], rightMax[i]) - height[i];
        }
        return ans;
    }
}

码上掘金代码链接:code.juejin.cn/api/raw/719…