文章目录
- 题目描述
 - 思路分析
 - 完整代码
 
题目描述
n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
 你需要按照以下要求,给这些孩子分发糖果:
 每个孩子至少分配到 1 个糖果。
 相邻两个孩子评分更高的孩子会获得更多的糖果。
 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
示例 1:
 输入:ratings = [1,0,2]
 输出:5
 解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。
示例 2:
 输入:ratings = [1,2,2]
 输出:4
 解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
 第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。
思路分析
本题中你评分再高也不一定能获得多的糖果。
 一句话,不关心学生评分,只关心学生的周围情况。
比如 学生 A 和学生B,排队情况 A在 B左。
- 若A>B 则A学生获得的糖果比B多一个。 -> 设为:左边大规则
 - 若A<B 则B学生获得的糖果比A多一个。 -> 设为:右边大规则
 
此时如果变成 ABC三个学生,则C需要同时满足 左边大规则和右边大规则。
 如果是ABCDEFGHIJK 等这么多学生呢,也就是说,所有学生都必须满足左边大规则和右边大规则。
流程:
- 设置两个全是1的数组 left 和right,长度等于题目所给ratings ,left存只符合左边大规则下的糖果分发情况,right同理。
 - 从左到右遍历,若 i+1 同学评分高于 i 同学,则left[i+1] = left[i]+1。
 - 同理填充right数组,但是需要从右到左遍历。
 - 最后每一个位置的同学需要同时满足左边大规则和右边大规则。所以 每一个位置取left和right相对位置的最大值。
 
为什么right需要反向遍历?
没绕进去,这就是一个很简单想通的问题,因为每个数的更新需要依靠右边的值,的所以要右边的值先更新,再更新左边的值。
我做这道题的时候绕进去了,结果就没想通哈哈,蠢得一。
举例:
 测试用例:[87,2,1]
反向遍历: 2>1 则评分为2的同学的糖果为 评分为1的同学的糖果数加1。评分为87的同学糖果数为 评分为2的同学的糖果数加1。变成了3,2,1
正向遍历: 87>2,则评分为87的同学糖果数 为 评分为2的同学的糖果数加1,初始为1,1,1。此时变成了2,1,1.。再次扫描到2的时候,评分为2的同学为 评分为1的同学的糖果数+1,糖果数就变成了2,2,1。这时候就发现不对了,还要修改87评分的同学的糖果数。所以正向遍历不行。
完整代码
class Solution:
def candy(self, ratings: List[int]) -> int:
left = [1] * len(ratings) # i+1 > i
right = [1] * len(ratings) # i+1 <i
count = 0
for i in range(len(right)-1):
if ratings[i] < ratings[i+1]:
left[i+1] = left[i]+1
for i in range(len(right)-1,0,-1):
if ratings[i-1] > ratings[i]:
right[i-1] = right[i]+1
count += max(left[i],right[i])
count += max(left[0],right[0])
return count
                










