前言
分发糖果
一、题目
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。
你需要按照以下要求,帮助老师给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/candy
二、解法
1.思路
最开始想的时候,就是从ZUO往右,无非就是 小于 大于 相等。
这里相等这个需要注意一下,刚开始我就没注意到为什么评分一样,糖果却可以不一样。
举个例子:
ratings : 【1,2,2,2,3】
result : 【1,2,1,1,2】
上升的时候一直叠加,下降的时候也是依次叠加,类似这样:
黄线即为判定上升和下降序列之间转换的位置.
只要找到每次变化的点,然后初始化值为1,重新叠加即可。
但是这里有个问题需要格外关注一下,类似这样:
如果下降序列长度大于之前上升的那个序列长度,那么变化点需要前移一位。
刚开始修修补补,写的不是很好:
class Solution():
def find(self,ratings):
Sum = 1
countRise = 1 #记录上升队列的长度
countDown = 0 #记录下降队列的长度
if len(ratings) == 1 :
return 1
if ratings[0] < ratings[1] :
pre = 1
elif ratings[0] == ratings[1] :
pre = 2
else :
pre = 3
#用数字 1 2 3 标记 < = > 以此来判断变化点的位置
for i in range(len(ratings)-1):
if ratings[i] < ratings[i+1] :
if pre == 1:
countRise += 1
Sum += countRise
else :
countRise = 2
Sum += countRise
pre = 1
elif ratings[i] == ratings[i+1] :
countRise = 1
countDown = 0
Sum += 1
pre = 2
else :
if pre == 3 :
countDown += 1
if countDown == countRise :
countDown += 1
# 此处判断 下降队列长度是否大于上升队列
Sum += countDown
elif pre == 2 :
countDown = 2
Sum += countDown
#如果前一组是相等的 这组开始下降 那么这组的起点应该是2
else :
countDown = 1
Sum += countDown
# 入股前一组是小于 这组开始下降 那么这组的起点应该是1
pre = 3
return Sum
# Run time: 68ms Memory consump:16.6MB
小于的话,起始值是1,可看第一幅图片。
看了其他人答案,发现自己想多了,用上升序列和下降序列两个变量即可,通过下降序列的长度来判断变化点的位置:
class Solution():
def find(self,ratings):
Sum = 1
riseSeq = 1 #起始上升序
fallSeq = 0 #下降序列
for i in range(len(ratings)-1):
if ratings[i] < ratings[i+1] :
if fallSeq != 0 :
riseSeq = 1
#判断变化点 对变量值进行初始化
fallSeq = 0
riseSeq += 1
Sum += riseSeq
elif ratings[i] == ratings[i+1] :
fallSeq = 0
riseSeq = 1
Sum += 1
else:
fallSeq += 1
if fallSeq == riseSeq :
fallSeq += 1
#判断下降序列是否大于上升序列
Sum += fallSeq
return Sum
# Run time: 64ms Memory consump:16.7MB
2.仿写
看了这个作者的答案,真的很强。
作者:mantoufan
链接:https://leetcode-cn.com/problems/candy/solution/dong-tai-gui-hua-qu-jian-dan-shuang-zhi-ca1bl/
想按照他的思路,用python3写出来。
从Zuo往右,然后从右往Zuo:
class Solution():
def find(self,ratings):
result = [1] * len(ratings) #初始化每个孩子都是1
for i in range(len(ratings)-1) : # 从Zuo往右遍历
if ratings[i+1] > ratings[i] :
result[i+1] = result[i] + 1
for j in range((len(ratings)-1),0,-1): #从右往Zuo遍历 这时候的取大应该考量一下
if ratings[j-1] > ratings[j] :
result[j-1] = max(result[j-1],result[j] + 1)
return sum(result)
# Run time: 72ms Memory consump:16.6MB
用Boolean值判定,就是把之前从Zuo往右一次遍历的方法的判定值改为布尔值:
class Solution():
def find(self,ratings):
Sum = 1
countRise = 1
countDown = 0
if len(ratings) == 1 :
return 1
if ratings[0] < ratings[1] :
pre = True
elif ratings[0] == ratings[1] :
pre = None
else :
pre = False #将之前的 1 2 3 改为了 true none false
for i in range(len(ratings)-1):
if ratings[i] < ratings[i+1] :
if pre :
countRise += 1
Sum += countRise
else :
countRise = 2
Sum += countRise
pre = True
elif ratings[i] == ratings[i+1] :
countRise = 1
countDown = 0
Sum += 1
pre = None
else :
if not pre :
countDown += 1
if countDown == countRise :
countDown += 1
Sum += countDown
elif pre :
countDown = 1
Sum += countDown
else :
countDown = 2
Sum += countDown
pre = False
return Sum
# Run time: 64ms Memory consump:16.6MB
第一次到了90%多,哈哈!