[主题创作之攒青豆]

53 阅读2分钟

当青训营遇上码上掘金

前言

虽然正在学习前端,但也深深了解到前端也需要掌握算法等知识。而算法类学习并不是死记硬背,而是要学习其思维,理解其步骤,并加以不断的练习.青训营快结束了,希望在此以此作为小练习,纪念一下这次艰苦的攒豆之旅。

任务描述-攒豆

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

image.png

任务分析

先简单分析一下,就是需要每次定下一根柱子为起始后,往后寻找仅次于自身高度的柱子or找到高于自身的柱子,然后利用长乘宽减去之间柱子的高度(好像有点抽象,但按图的意思是柱子的宽度不可忽略,单位为1)

进一步分析:

仔细想想,上一步分析有很多漏洞,或者说虽然很具象化但用代码实现起来很难。所以按代码的逻辑分析为:每次都要寻找当前列左右最高的柱子,形成一个“桶”。那么就可以遍历数组,将第i列左右最高墙找出,存起。然后再按列求出每一列存的豆子,只要当前列柱子高度小于左右最高柱,则当前列豆子数为左右最高柱之中,较低的高度减去当前高度。

关键点:

  • 只有左右最高柱均大于当前列的height时,当前列才会有豆子
  • 首列和末列不用考虑

任务实现

public static int col(int[] height) {
    int len=height.length;
    int sum=0;
    int []left = new int[len];
    int []right = new int[len];
    for(int i=1;i<len-1;i++)
    {
      left[i] = Math.max(left[i-1], height[i-1]);
    }
    for(int i=len-2;i>0;i--)
    {
      right[i] = Math.max(right[i+1], height[i+1]);
    }

    for(int i=1;i<len-1;i++)
    {
      if(right[i]<left[i])
      {
        if(right[i]>height[i])
          sum+=right[i] - height[i];
      }
      else
      {
        if(left[i]>height[i])
          sum+=left[i] - height[i];
      }
    }
    return sum;
  }

结语

无论是什么任务,都要去逐步剖析,逐步解决问题,纸上谈兵对于编程而言是万万不可的。有错有bug很正常,慢慢去修改就是了。在本次编程过程中,第一个第二个版本的写法都会报错,都是一些基础问题,还有一次结果错了,是忘了加上“当前列低于左右最高列”的判断,所以每一个细节都要注意。