AlgoMooc
你已开通华为OD训练营权益,还差最后一步——完成入营激活(兑换课程 + 加飞书 + 登记服务群),即可解锁全部课程与专属服务。去激活 →
← OD 20 天课程

华为 OD 训练营 · 题解精讲

LC135. 分发糖果

配套讲解:视频讲解

LC135. 分发糖果 视频地址:https://uha.xet.tech/s/ifcWl

题目描述

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求,给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果。 相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。 示例 1: 输入:ratings = [1,0,2] 输出:5 解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。 示例 2: 输入:ratings = [1,2,2] 输出:4 解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。 第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。 提示: n == ratings.length 1 <= n <= 2 * 10^4 0 <= ratings[i] <= 2 * 10^4

题目解析

解题思路

本题要求相邻评分更高的孩子获得更多糖果,且总糖果数最少。核心思想是将规则拆分为两个方向分别处理,再合并结果。

  • 左规则:从左向右遍历,若当前孩子评分高于左边,则糖果数至少比左边多1。
  • 右规则:从右向左遍历,若当前孩子评分高于右边,则糖果数至少比右边多1。

最终每个孩子的糖果数需同时满足两个规则,因此取两次计算结果的最大值

数据结构:一维数组 candys 存储每个孩子糖果数,初始全为1。

关键步骤

1. 初始化:所有孩子先分1颗糖,保证最低要求。 2. 左遍历i 从1到n-1,若 ratings[i] > ratings[i-1],则 candys[i] = candys[i-1] + 1。 3. 右遍历并累加i 从n-2到0,若 ratings[i] > ratings[i+1],则 candys[i] = max(candys[i], candys[i+1] + 1)。同时累加结果,从最右孩子开始。


示例 ratings = [1,0,2]
左遍历后 candys = [1,1,2]  (因为 0<2 触发更新)
右遍历:i=1时 0<1? 否,不变;i=0时 1>0? 是,candys[0]=max(1, candys[1]+1=2)=2
最终 candys = [2,1,2],总和5

复杂度分析

  • 时间复杂度:O(n),两次线性遍历,n为数组长度。
  • 空间复杂度:O(n),用于存储糖果数组。

参考代码

class Solution:
    def candy(self, ratings: List[int]) -> int:
        # 存储每个孩子的糖果        
        # 先给所有孩子 1 颗糖
        candys = [1 for _ in range(len(ratings))]

        # 从左至右遍历数组 ratings
        for i in range( 1 , len(ratings)) :

            # 如果发现当前孩子的评分比【左边】的更高
            if ratings[i] > ratings[i - 1] : 

                # 那么当前孩子的糖果数量需要比【左边】孩子的糖果数量多 1 个
                candys[i] = candys[i - 1] + 1

        
        # 记录糖果数量,初始为最右边的值
        result = candys[-1]

        # 从右至左遍历数组 ratings
        for i in range( len(ratings) - 2 , -1 , - 1 ) :

            # 如果发现当前孩子的评分比【右边】的更高
            if ratings[i] > ratings[i + 1] : 
                
                # 那么当前孩子的糖果数量需要比【右边】孩子的糖果数量多 1 个
                # 当前孩子在第一轮循环中已经设置了值
                # 所以取这两个值的最大值
                # 这样同时满足左规则和右规则 
                candys[i] = max( candys[i + 1] + 1  , candys[i]) 

            

            # candys[i] 已经是符合左规则和右规则的值了
            # 累加到 result 上面
            result += candys[i]
        

        # 返回结果
        return result