LeetCode 135. 分发糖果(C语言)| 贪心算法 + 双向遍历详解

一、题目描述

有 n 个孩子站成一排,每个孩子都有一个评分 ratings[i]。

你需要给这些孩子分发糖果,满足以下规则:

  1. 每个孩子至少分到 1 个糖果

  2. 评分更高的孩子必须比相邻孩子获得更多糖果

要求计算 最少需要多少个糖果。

示例1

复制代码
输入: ratings = [1,0,2]
输出: 5

解释:

复制代码
糖果分配: [2,1,2]

示例2

复制代码
输入: ratings = [1,2,2]
输出: 4

解释:

复制代码
糖果分配: [1,2,1]

二、问题分析

我们只需要关注 相邻孩子之间的评分关系。

如果:

复制代码
ratings[i] > ratings[i-1]

说明 右边孩子评分更高,必须给更多糖果。

如果:

复制代码
ratings[i] > ratings[i+1]

说明 左边孩子评分更高,必须给更多糖果。

问题在于:

一次遍历无法同时满足两个方向的约束。

因此需要:

复制代码
两次遍历

三、贪心算法思路

核心思想:

复制代码
先保证左规则,再保证右规则

步骤如下:

1 初始化糖果

每个孩子至少一个糖果:

复制代码
candies = [1,1,1,1,...]

2 从左向右遍历

如果右边评分更高:

复制代码
ratings[i] > ratings[i-1]

则:

复制代码
candies[i] = candies[i-1] + 1

示例:

复制代码
ratings = [1,2,3]

变化过程:

复制代码
初始   [1,1,1]
遍历后 [1,2,3]

3 从右向左遍历

如果左边评分更高:

复制代码
ratings[i] > ratings[i+1]

需要调整:

复制代码
candies[i] = max(candies[i], candies[i+1] + 1)

为什么要 max?

因为 第一次遍历可能已经分配更多糖果,不能被覆盖。


四、图解过程

示例:

复制代码
ratings = [1,0,2]

第一步 初始化

复制代码
ratings  [1,0,2]
candies  [1,1,1]

第二步 左 → 右

复制代码
0 < 1 → 不变
2 > 0 → candies[2] = 2

结果

复制代码
candies = [1,1,2]

第三步 右 → 左

复制代码
0 < 2 → 不变
1 > 0 → candies[0] = 2

最终

复制代码
candies = [2,1,2]

计算总数

复制代码
2 + 1 + 2 = 5

五、完整 C 语言代码

复制代码
#include <stdlib.h>

int candy(int* ratings, int ratingsSize) {
    if (ratingsSize == 0) return 0;

    int* candies = (int*)malloc(sizeof(int) * ratingsSize);

    // 每个孩子至少1颗糖
    for (int i = 0; i < ratingsSize; i++) {
        candies[i] = 1;
    }

    // 从左向右遍历
    for (int i = 1; i < ratingsSize; i++) {
        if (ratings[i] > ratings[i - 1]) {
            candies[i] = candies[i - 1] + 1;
        }
    }

    // 从右向左遍历
    for (int i = ratingsSize - 2; i >= 0; i--) {
        if (ratings[i] > ratings[i + 1] && candies[i] <= candies[i + 1]) {
            candies[i] = candies[i + 1] + 1;
        }
    }

    int sum = 0;

    for (int i = 0; i < ratingsSize; i++) {
        sum += candies[i];
    }

    free(candies);
    return sum;
}

六、复杂度分析

时间复杂度

复制代码
O(n)

遍历数组两次。


空间复杂度

复制代码
O(n)

使用了一个 candies 数组。


七、算法总结

这道题是 经典贪心问题。

关键思想:

复制代码
局部最优 → 全局最优

策略:

  1. 每人至少一个糖果

  2. 左→右保证右边评分高

  3. 右→左保证左边评分高

  4. 取最大值避免覆盖

最终即可得到 最少糖果数。


八、同类贪心题推荐

如果你在刷 LeetCode Top150,这几题属于同一思路:

题号 题目
55 跳跃游戏
45 跳跃游戏 II
134 加油站
135 分发糖果

相关推荐
听风说ml14 小时前
socket编程 【C语言】
c语言·udp·tcp·socket编程
学逆向的15 小时前
C 局部静态变量
c语言·开发语言·网络安全
UIU11415 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
论文复现现场16 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi16 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
秋天的怀念_David17 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院18 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng18 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
叉烧滑蛋20 小时前
B站台湾大学郭彦甫|MATLAB 学习笔记|04 变量与档案存取
数据结构
j7~21 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归