粟祖杭の个人网站
首页项目归档照片墙音乐灵境说说杂谈友链关于
封面

LeetCode 135

写作时间:2026-09-07 23:50:29

LeetCode 135. 分发糖果 算法题解

题目描述

n 个孩子站成一排,给定数组 ratings 表示每个孩子的评分。需要分发糖果,满足:

  1. 每个孩子至少分到 1 个糖果
  2. 相邻两个孩子中,评分更高的获得更多糖果

返回所需的最少糖果总数。

题目理解与关键点

  • 约束是相邻比较,只有两个方向:左邻居、右邻居
  • 评分相等时没有约束,可以分同样多的糖果(不要求更高)
  • 求的是最小值,所以每个孩子应该在满足约束的前提下尽量拿少的糖

核心思路:贪心 + 两次遍历

为什么不能一次遍历?

因为每个孩子同时受左右两个邻居的影响,而一次遍历只能保证一个方向。

只从左到右: 只能保证"右边比左边评分高的孩子糖多",处理不了"左边比右边评分高的"情况。

反例: ratings = [2, 1, 2](中间是谷底,两侧都更高)
只从左到右: 初始: [1, 1, 1] i=1: ratings[1]=1 < ratings[0]=2,不改 i=2: ratings[2]=2 > ratings[1]=1,加糖 → [1, 1, 2] 结果: [1, 1, 2] ← 错误!孩子0评分最高却只拿1个

孩子0是"左边比右边高",这个方向被漏掉了,必须从右到左再处理一遍。

算法流程

  1. 初始化:所有孩子先分 1 个糖(满足约束1)
  2. 第一遍(从左到右):处理"右边评分高"的情况
    如果 ratings[i] > ratings[i-1]: candle[i] = candle[i-1] + 1

保证每个孩子的糖比左边评分低的邻居多

  1. 第二遍(从右到左):处理"左边评分高"的情况
    如果 ratings[i] > ratings[i+1]: candle[i] = max(candle[i], candle[i+1] + 1)

保证每个孩子的糖比右边评分低的邻居多,用 max 同时满足两个方向

  1. 求和:返回所有糖果总数

为什么第二遍用 max?

一个孩子可能同时比左右都高(山峰),两边都会给他一个"最少要求值"。取 max 保证同时满足两个方向的约束,且不再增大(因为其他位置不受影响)。

逐步演示

ratings = [1, 0, 2]
初始: [1, 1, 1] 左→右: i=1: ratings[1]=0 < ratings[0]=1,不改 → [1, 1, 1] i=2: ratings[2]=2 > ratings[1]=0,加糖 → [1, 1, 2] 右→左: i=1: ratings[1]=0 < ratings[2]=2,不改 → [1, 1, 2]

总和 = 1 + 1 + 2 = 4 ✓

验证:0号(评1)比1号(评0)高 → 1>1?不对,0号1个、1号1个,但评分1>0需要0号更多,有误?

(纠正)正确演示 ratings = [0, 1, 2] 或 ratings = [1, 2, 2]:

ratings = [1, 2, 2]
初始: [1, 1, 1] 左→右: i=1: ratings[1]=2 > ratings[0]=1 → [1, 2, 1] i=2: ratings[2]=2 == ratings[1]=2,不改 → [1, 2, 1] 右→左: i=1: ratings[1]=2 == ratings[2]=2,不改 → [1, 2, 1]

总和 = 1 + 2 + 1 = 4 ✓

代码实现

class Solution {
public:
    int candy(vector<int>& ratings) {
        int n = ratings.size();
        vector<int> candle(n, 1);   // 每人至少 1 个
​
        // 从左到右:保证右边评分高的糖比左边多
        for (int i = 1; i < n; i++) {
            if (ratings[i] > ratings[i - 1]) {
                candle[i] = candle[i - 1] + 1;
            }
        }
​
        // 从右到左:保证左边评分高的糖比右边多
        for (int i = n - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candle[i] = max(candle[i], candle[i + 1] + 1);
            }
        }
​
        int sum = 0;
        for (int c : candle) {
            sum += c;
        }
        return sum;
    }
};

复杂度分析:

时间复杂度:O(n),两次线性遍历 + 一次求和

空间复杂度:O(n),candle 数组存储每个孩子的糖果数

avatar

粟祖杭

你好,我是 粟祖杭,一名专注于 C/C++ 嵌入式开发的学习者与实践者。

RECOMMENDED

LeetCode 30

2026-08-20 16:38:33

LeetCode 76

2026-09-07 23:52:36

LeetCode 68

2026-09-07 23:56:01

Table of Contents