当青训营遇上码上掘金
1 问题重现
青训营主题创作活动中有如下问题:
主题4 攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
给出一个例子如图所示:
这个例子的输入为
5 0 2 1 4 0 1 0 3
输出为17
2 问题分析
(题外话:这道题让我们想到了心心念念的青豆哈)
观察此题可以得出如下规律:
- 整个问题可以看成多个数字组成了多个容器
- 一个可装青豆的容器由左边和右边组成,一个容器的最大体积为数字小的一边乘以两个边之间的距离(即容器中间的数字数量)
- 一个容器中的数字即为障碍,计算该容器的最大体积时要减去(即减去容器中间的数字之和)
3 解决方案
从分析中可得的规律,可总结出问题的解决逻辑如下:
- 划分容器
- 计算容器体积
让我们来依次解决提出的上述步骤:
-
划分容器:
设立两个标志:左标志和右标志,分别代表容器的两边。
第一个容器的左标志是数组的第一个数,那么右边的标志怎么找呢?
就需要分情况讨论:
- 当右边有比左标志代表的数更大的数时,从左往右遍历,只要遇到一个比左标志更大的数,那么它就是右标志。计算容器体积即可
- 当右边没有比左标志代表的数更大的数时,利用python的max函数和index函数找出右边最大的数,此时它就是我们要找的右标志,计算容器体积即可。
-
计算容积体积:
数字小的一边乘以两个边之间的距离(即容器中间的数字数量)减去容器中间的数字之和
4 代码
python3
num_string = input("height=")
num_list=num_string.split(" ")
print(num_list)
left_flag=0
left_value=int(num_list[left_flag])
right_flag=0
right_value=0
area=0
temp_area=0
deb_area=0
while True:
if left_flag==len(num_list)-1:
break
max_value=int(max(num_list[left_flag+1:]))
if max_value==0:
break
if max_value<=left_value:
right_flag=num_list.index(str(max_value))
right_value=max_value
if right_flag-1==left_flag:
left_flag=right_flag
continue
for i in num_list[left_flag+1:right_flag]:
deb_area = deb_area + int(i)
temp_area = right_value * (right_flag-left_flag-1) - deb_area
area+=temp_area
print(temp_area)
temp_area=0
deb_area=0
left_flag=right_flag
right_flag=0
continue
if max_value>left_value:
right_flag=left_flag
for i in num_list[left_flag+1:]:
i=int(i)
right_flag+=1
if i >= left_value:
right_value=i
for j in num_list[left_flag+1:right_flag]:
deb_area=deb_area+j
temp_area=left_value*(right_flag-left_flag-1)-deb_area
area+=temp_area
temp_area=0
deb_area=0
left_flag=right_flag
right_flag=0
break
print(area)