文章目录

  • ​​题目描述​​
  • ​​思路分析​​
  • ​​完整代码​​

题目描述

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