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 分发糖果

相关推荐
阿里嘎多哈基米1 小时前
速通Hot100-Day07——栈
数据结构·算法·leetcode··队列·hot100
2401_900151541 小时前
自定义异常类设计
开发语言·c++·算法
努力学算法的蒟蒻1 小时前
day113(3.15)——leetcode面试经典150
算法·leetcode·职场和发展
李斯啦果1 小时前
【C语言】统计对称素数
c语言·开发语言
一叶落4382 小时前
LeetCode 42. 接雨水(C语言详解)——双指针经典解法
c语言·数据结构·c++·算法·leetcode
寂柒2 小时前
哈希桶——模拟实现哈希表
数据结构·c++·算法
郝学胜-神的一滴2 小时前
一序平衡,括号归真:单括号匹配算法的优雅美学
java·前端·数据结构·c++·python·算法
小O的算法实验室2 小时前
2026年IEEE TCYB SCI1区TOP,电动采摘机器人多目标任务分配:一种分层路径重构方法,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
CSDN_kada2 小时前
杭电网安复试编程Day19
开发语言·c++·算法