当青训营遇上码上掘金
题目描述
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
思路
这道题目咋一看就很熟悉了,不就是接雨水换个名字接青豆,所以就很简单了。
方法一:
按行计算:先计算第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 层。
。。。。。。
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
}