「青训营 X 码上掘金」主题 4:攒青豆

64 阅读2分钟

当青训营遇上码上掘金

主题 4:攒青豆

现有 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 个单位的青豆。
复制代码

思路

可以把每一根柱子都当作一个区域,那么就是每一个区域的豆子就是根据自身左边最高的和右边最高的还有自身的高度计算出来

解法

动态规划

预处理:

  • 从左往右遍历计算出每根柱子左边最高的
  • 从右往左遍历计算出每根柱子右边最高的
  • 预处理完,就可以进行最后一次遍历了,然后直接算出青豆数即可
  • 时间复杂度 O(n) 空间复杂度 O(n)

代码

package main

import "fmt"

func max(a int ,b int) int {
    if a > b {
        return a;
    }else {
      return b;  
    }
}

func min(a int ,b int) int {
    if a > b {
        return b;
    }else {
      return a;  
    }
}

func main() {
  //读取输入
  var n int;
  fmt.Scan(&n)
  columns := make([]int,n)
  for i  := 0; i < n; i++ {
    var element int
		fmt.Scan(&element)
		columns=append(columns,element)
  }
	
	leftMax := make([]int, n)
	rightMax := make([]int, n)
	leftMax[0] = columns[0]
	rightMax[n-1] = columns[n-1]
  //从左往右遍历
	for i := 1; i < n; i++ {
		leftMax[i] = max(leftMax[i-1], columns[i])
	}
  //从右往遍历
	for i := n - 2; i >= 0; i-- {
		rightMax[i] = max(rightMax[i+1], columns[i])
	}
	ans := 0
	for i := 0; i < n; i++ {
		ans += min(leftMax[i], rightMax[i]) - columns[i]
	}
  fmt.Print("可以装%v的青豆",ans)
}

结果测试:

image.png 但是不知道为啥掘金这里的运行不出来 完整代码已放到码上掘金上。

总结

其实还有很多种解法,双指针和单调栈这些都可以试试,但是这里就不做详细的描述了