「青训营 X 码上掘金」主题创作之攒青豆

67 阅读2分钟

当青训营遇上码上掘金

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


初见题目

  • 现有 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 个单位的青豆。

刚刚开始看见这个题目的时候,心中感慨万分,为什么策划们要出这个题目,或者说题目为什么要起这个名字,不过确实很应景,作为青训营的一员,在学习到知识的基础上,攒青豆似乎是最重要的事情,攒青豆的规则和活动有很多,如何才能不混乱,慢慢的攒够青豆呢!本人实力不济,算法题刷的不多,写出的算法或许不是最优解。不如先来一道攒青豆的算法题清醒下脑子吧!!!

题目思路

  • 首先能够攒住青豆的前提是两侧需要有柱子包围,即左右两侧的高度都要大于0。正如“短板效应”一样,所能攒住的青豆要取决于矮的柱子。
  • 那么我们就可以用(双指针法)两个int值来记录左边和右边的已知最高高度,随着指针的移动,int值会发生变化。
  • 左指针l指向左边第一个柱子,右指针k指向右边第一个柱子,然后从左向右遍历
  • 若遍历点的柱子高度小于l和k的值,那么当前遍历点所能存储的青豆个数为min{l,k}-当前柱子高度
  • 若遍历点的柱子高度大于l,则l更新为当前柱子高度,左指针向右移动
  • 比较左右指针的值,让值小的一方进行移动

代码如下所示

 public int qingdou(int[] height)
   {
      if(height==null||height.length==0){
            return 0;
        }
        int left = 0;
        int right = height.length-1;
        int sum = 0;
        int l = height[left];
        int k = height[right];
        while(left<right){
            if(l<=k){
                if(l>height[left+1]){
                    sum+=l-height[left+1];
                }else{
                    l = height[left+1];
                }
                left++;
            }else{
                if(k>height[right-1]){
                    sum+=k-height[right-1];
                }else{
                    k = height[right-1];
                }
                right--;
            }
        }
        return sum;
   }