主题4:攒青豆|「青训营 X 码上掘金」主题创作活动入营版

107 阅读2分钟

当青训营遇上码上掘金

本文以作品参加青训营入营活动。

  1. 前言

    熟悉的配方,熟悉的味道。这不就是鼎鼎大名的“接雨水”?对于本题广为人知的解法(单调栈,动态规划,双指针)不再赘述,一些大神的解法比比皆是。在这里讲的解法是我第一次接触到这个题目所用的解法,并且将原本的C++解法换成了最近学习的GO语言解法,所以语法略显笨拙。

  2. 题目分析

    首先柱子宽度定为1,即要计算整个数组代表的柱子所围起来的空隙个数,每一个单位的空隙可以攒1单位的青豆,最后计算所积累的青豆的单位数。

  3. 代码原理

    柱子高度数组height

    1、遍历整个数组height,找到最高的柱子高度smax

    2、定义3个smax+1的数组cnt,mymin,mymax,再次遍历原数组height,cnt计算每个高度出现的个数,mymin[i]记录第一个高度大于等于当前高度i的位置,mymax[i]记录最后一个高度大于等于当前高度i的位置

    3、遍历每一个大于等于1的高度,计算当前高度能够攒到青豆的总数cur:

    cur=mymax[i]-mymin[i]-cnt[i]+1

    4、将所有高度攒到的青豆数目加起来就是我们所需要的结果。

  4. 复杂度分析 寻找最高的柱子O(n),计算mymax、mymin的O(n^2),但其实mymax和mymin的所需要的时间复杂度是小于O(n^2)的,所以最后程序可以通过leetcode的接雨水的验证。

    var smax int
    var ref int
    for _,i:=range height{
        smax=max(smax,i)
    }
    // fmt.Println(smax)
    cnt:=make([]int,smax+1)
    mymin:=make([]int,smax+1)
    mymax:=make([]int,smax+1)
    for _,i:=range height{
        cnt[i]++
    }
    for i:=0;i<smax+1;i++{
        mymax[i]=smax;
    }
    for i:=0;i<smax+1;i++{
        for j:=0;j<len(height);j++{
            if(height[j]>=i){
                mymin[i]=j
                break
            }
        }
        for j:=len(height)-1;j>=0;j--{
            if(height[j]>=i){
                mymax[i]=j
                break
            }
        }
    }
    // for i:=0;i<smax+1;i++{
    
    //     fmt.Println(mymax[i])
    // }
    for i:=smax-1;i>=0;i--{
        cnt[i]=cnt[i+1]+cnt[i]
    }
    for i:=0;i<smax+1;i++{
        ref+=mymax[i]-mymin[i]-cnt[i]+1
    }
    
    
    return ref
    }
    
    
    func max(x int,y int) int{
    if x>y {
        return x
    }
        return y 
    }
    func min(x int,y int) int{
        if (x<y) {
            return x
        }
        return y
    }