[青训营X码上掘金]主题创作活动

46 阅读2分钟

当青训营遇上码上掘金,本人选择的主题为主题四“攒青豆”。

一、题目内容介绍

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

二、具体算法思想

找到最高峰。分别从左右遍历。正向遍历,当下一个峰小于当前峰,可以接青豆,同理反向遍历

  • 我们以列为单位去分割总任务,最后要求总的接水量,其实就是把每一列的接水量加起来的总和。
  • 要想要能接水,那么左边的柱子高度必须严格大于该列的高度,右边的柱子也必须严格大于该列高度(即:左右与该列要能形成凹槽)。 此时栈内是递减的,下一个将要进站的元素是下标为6的元素(高度为1),如果它直接进栈就会破坏单调栈,因此,需要元素出栈,那么下标为5的元素就要出栈,在它出栈的同时,我们可以直接计算出这个出栈的元素可以收集的雨水量,但是有一个注意点是,在这里每个小凹槽按行收集比按列收集要方便。 首先,我们要记得我们维护的栈是一个非递增的栈。

三、代码实现部分

采用JAVA语言编写

    int trap(int[] h) {
    int sum = 0;
    int l=0;
    int[] f=new int[h.length];
    int[] aar=new int[h.length];
    if (h.length<2) {//长度小于2,接不了
        return 0;
    }
    for (int i = 0; i <h.length; i++) {//找到最高峰
        aar[i]=h[i];
    }
    int aar_Max = aar[0];              
    for(int i=0;i<aar.length;i++){
        if(aar[i]>aar_Max){//
            aar_Max=aar[i];
            l = i;
        }
    }
    for (int i = 1; i <l; i++) {//正向遍历
        if(h[i-1]>h[i]){
            f[i]=h[i-1]-h[i];
            h[i]=h[i-1];
        }else {
            f[i]=0;
        }
    }
    for (int i = h.length-2; i > l; i--) {//反向遍历
        if(h[i+1]>h[i]){
            f[i]=h[i+1]-h[i];
            h[i]=h[i+1];
        }else {
            f[i]=0;
        }
    }
    for(int i=0;i<h.length;i++){
        sum = sum+ f[i];
    }
    return sum;
}


 

我们其实在总体遍历的过程中是按列遍历的,然后不断找到可以接水的凹槽,对于每个凹槽我们其实是按行的方式去计算出其盛水量的,我们在出栈的过程中其实是不断找寻左挡板的过程,这过程中会遇见接不了水的情况(我们也可以认为接水量为0,依旧把他加入最后结果中)。

四、个人总结

 通过参与此次活动,让我对代码的编写有了更加清晰和深刻的理解。对后端这个岗位有了更清晰的了解。了解到了后端发展的历程,扩宽了我的知识面。