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

59 阅读3分钟

这是我参与「第五届青训营」伴学笔记创作活动的第18天。

题目描述

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

以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17个单位的青豆。

思路1

采用遍历的办法,从左向右遍历数组,来计算能接住多少青豆,遍历从数组下标i = 1开始。
i = 1,height[1] = 0,左侧最大值为5,右侧最大值为4,i = 1处可以接到4颗青豆。
i = 2,height[2] = 2,左侧最大值为5,右侧最大值为4,i = 2处可以接到4 - 2 = 2颗青豆。
i = 3,height[3] = 1,左侧最大值为5,右侧最大值为4,i = 3处可以接到4 - 1 = 3颗青豆。
i = 4,height[4] = 4,左侧最大值为5,右侧没有比4更大的值,i = 4处可以接到0颗青豆。
i = 5,height[5] = 0,左侧最大值为5,右侧最大值为3,i = 5处可以接到3颗青豆。
i = 6,height[6] = 1,左侧最大值为5,右侧最大值为3,i = 6处可以接到3 - 1 = 2颗青豆。
i = 7,height[7] = 0,左侧最大值为5,右侧最大值为3,i = 7处可以接到3颗青豆。
i = 8,height[8] = 3,左侧最大值为5,右侧没有比3更大的值,i = 8处可以接到0颗青豆。
遍历整个数组就可以得出一共能接到17青豆。

思路2

在一个或若干个元素的两侧存在高度差才能够攒下青豆,可以先从右侧找到一个最大值,将最大值的数据保存为数组,然后再从左侧找到一个最大值,将最大值的数据保存为数组,最后结果统计用左侧最大值与右侧最大值取最小值再减去底部高度,所得的值就是这个点所能攒下的最多的青豆的值。

解题代码

解析

(1)从右到左对height数组进行遍历,将最大值保存为temp_right数组,可得temp_right数组为[5,4,4,4,4,3,3,3,3]。

var temp_right [9]int
temp_right[length-1] = height[length-1]
for i := length - 2; i >= 0; i-- {
    if temp_right[i+1] > height[i] {
        temp_right[i] = temp_right[i+1]
    }else{
        temp_right[i] = height[i]
    }
}

(2)从左到右对height数组进行遍历,将最大值保存为temp_light数组,可得temp_light数组为[5,5,5,5,6,6,6,6,6]。

var temp_left [9]int
temp_left[0] = height[0]
for i := 1; i < length; i++ {
    if temp_left[i-1] > height[i] {
        temp_left[i] = temp_left[i-1]
    }else{
        temp_left[i] = height[i]
    }
}

(3)左侧最大值与右侧最大值取最小值,再减去底部高度,最终累加结果即为攒得得青豆数量。

num := 0
for i := 0; i < length; i++ {
    t := 0
    if temp_left[i] < temp_right[i] {
        t = temp_left[i]
    }else{
        t = temp_right[i]
    }
    num += t - height[i]
}
return num