当青训营遇上码上掘金 | 攒青豆

52 阅读2分钟

当青训营遇上码上掘金

题目描述

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

image.png

思路

这道题目咋一看就很熟悉了,不就是接雨水换个名字接青豆,所以就很简单了。

方法一:

按行计算:先计算第1行,再计算第2行,再计算第3行 。。。

比如高度为第 i 的行,从左往右开始遍历,temp临时记录边际之间豆子,小于 i 就加1个豆子,大于等于 i 时就切换边际,同时把temp加入到result,重置temp

用一个 flag 标记第一个不为空的高度

时间复杂度:O(max * len),最大高度和数组长度

高度小于 1,temp ++,

高度大于等于 1,ans = ans + temp,temp = 0。

temp 初始化为 0,ans = 0

height[0] 等于 0 < 1,不更新。

height[1] 等于 1 >= 1,开始更新 temp。

height[2] 等于 0 < 1,temp = temp + 1 = 1。

height[3] 等于 2 >= 1,ans = ans + temp = 1,temp = 0。

height[4] 等于 1 >= 1,ans = ans + temp = 1,temp = 0。

height[5] 等于 0 < 1,temp = temp + 1 = 1。

height[6] 等于 1 >= 1,ans = ans + temp = 2,temp = 0。

剩下的 height[7] 到最后,高度都大于等于 1,更新 ans = ans + temp = 2,temp = 0。而其实 temp 一直都是 0,所以 ans 没有变化。

再求第 2 行的水。

高度小于 2,temp ++,高度大于等于 2,ans = ans + temp,temp = 0。

temp 初始化为 0,ans 此时等于 2。

height[0] 等于 0 < 2,不更新。

height[1] 等于 1 < 2,不更新。

height[2] 等于 0 < 2,不更新。

height[3] 等于 2 >= 2,开始更新

height[4] 等于 1 < 2,temp = temp + 1 = 1。

height[5] 等于 0 < 2,temp = temp + 1 = 2。

height[6] 等于 1 < 2,temp = temp + 1 = 3。

height[7] 等于 3 >= 2,ans = ans + temp = 5,temp = 0。

height[8] 等于 2 >= 2,ans = ans + temp = 3,temp = 0。

height[9] 等于 1 < 2,temp = temp + 1 = 1。

height[10] 等于 2 >= 2,ans = ans + temp = 6,temp = 0。

height[11] 等于 1 < 2,temp = temp + 1 = 1。

然后结束循环,此时的 ans 就是6。

再看第 3 层。

。。。。。。

image.png

func trap1(height []int) int {
   result := 0
   max := getMax(height)
   for i := 1; i < max + 1; i++ {
      flag := false
      temp := 0
      for j := 0; j < len(height); j++ {
         if height[j] >= i {
            flag = true
            result += temp
            temp = 0
         }
         if flag && height[j] < i {
            temp++
         }
      }
   }
   return result
}
func getMax(height []int) int {
   temp := 0
   for i := 0; i < len(height); i++ {
      if height[i] > temp {
         temp = height[i]
      }
   }
   return temp
}

方法二

按列计算:类似木桶,当前列的左右两边分别保存下来最大的高度,可想而知,当前列可接豆子最大不能超过这两个边际的较小值,不然不就漏了。

时间复杂度:O(n)

func trap2(height []int) int {
   res, left, right, maxLeft, maxRight := 0, 0, len(height)-1, 0, 0
   for left <= right {
      if height[left] <= height[right] {
         if height[left] > maxLeft {
            maxLeft = height[left]
         } else {
            res += maxLeft - height[left]
         }
         left++
      } else {
         if height[right] >= maxRight {
            maxRight = height[right]
         } else {
            res += maxRight - height[right]
         }
         right--
      }
   }
   return res
}