当青训营遇上码上掘金,本次使用Python实现攒青豆,个人理解比较愚笨。
说实话,最开始没有读懂题目的意思,因为题目直接问了接住多少青豆,但是我觉得告诉了柱子的宽度,青豆的长度(或者宽度,如果有的是倒立的,想法比较奇怪哈哈)都不知道,怎么知道接住了多少青豆,然后看到别人说的接雨水,特地看了一下题目的要求(题目给出的是接住多少单位的雨水),后面就明白了整个题目的意思(挡住多少单位的青豆)。
首先是大体思路,如果柱子高度heightList=[5,0,2,1,4,0,1,0,3],需要实现挡住,至少需要两个柱子并且高度大于0,所以这里就只判断两个柱子,第一个柱子为5,第三个柱子高度为2(0不考虑),根据这里,可以挡住2个单位的青豆(对于第二个柱子来说),继续往后遍历,柱子高度为1时,能挡住1个单位青豆(现在不看第三个柱子,当作整个只有两个柱子),柱子高度为4时,能挡住4个单位青豆......也就是第二个柱子(高度为0),由左边第一个柱子与其他柱子两两组合,可以挡住的青豆单位为[2,1,4,1,3],那这里就是取最大值4(为什么不取2?因为对于第二个高度为0的柱子可以第一个柱子和第五个柱子);接下来是第三个柱子,刚刚说了高度为0的柱子可以攒下,为什么考虑柱子高度为2,如果2的左右两边分别为5和4,那么柱子2上面也是可以攒下青豆),按照刚刚的思路,由左边第一个柱子与其他柱子(选择高度大于0的柱子)两两组合,可以挡住的青豆单位为[0,2,0,1],那这里就是取最大值2......但是为什么都是取得左边第一个与每次计算的柱子的右边组合,这是因为第一个柱子的高度最高,如果左边第一个柱子高度为5,第二个柱子高度为8,那后面计算第三个柱子及其之后攒下的青豆时,左边选择的至少是8而不是5。
然后整合一下整体思路,针对每次研究的柱子C,都是从遍历左边找到最高的柱子A,同时遍历从右边找到最高的柱子B,然后取min(A,B),再用min(A,B)- C。所以整个算法就可以实现编程(这里就是用了最简单的遍历,没有考虑其他优化)
def CalSum(heightList):
sum=0
for i in range (len(heightList)):
sumLeft = 0
for j in range(0,i): #每次从左到右
sumLeft=max(sumLeft,heightList[j])
• sumRight = 0
• for k in range(-1,(i-len(heightList)),-1): #每次从右到左
• sumRight=max(sumRight,heightList[k])
• if (min(sumLeft,sumRight)>heightList[i]):
• sum=sum+min(sumLeft,sumRight)-heightList[i]
return sum
if __name__ == '__main__':
# 这里使用input函数编译不通过,sublime不支持input函数,但是本地调试可以通过
#所以只能直接定义heightList列表
# n=int(input("请输入柱子的个数n:"))
# heightList=[] #列表存储每个柱子的高度
# for i in range(n):
# temp=int(input("请输入柱子的高度:"))
# heightList.append(temp)
# print(str(n)+"个柱子的高度分别为:")
# print(heightList)
heightList=[5,0,2,1,4,0,1,0,3]
print( "可以接到的青豆为:",CalSum(heightList))
输出结果:
因为码上掘金不能直接使用input,所以注释了,本地调试可以取消注释红色部分,注释掉 heightList=[5,0,2,1,4,0,1,0,3],由自己输入数据。