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

相关推荐
OOJO4 小时前
c++---list介绍
c语言·开发语言·数据结构·c++·算法·list
别或许5 小时前
1、高数----函数极限与连续(知识总结)
算法
派大星~课堂5 小时前
【力扣-142. 环形链表2 ✨】Python笔记
python·leetcode·链表
田梓燊5 小时前
code 560
数据结构·算法·哈希算法
笨笨饿6 小时前
29_Z变换在工程中的实际意义
c语言·开发语言·人工智能·单片机·mcu·算法·机器人
kobesdu6 小时前
综合强度信息的激光雷达去拖尾算法解析和源码实现
算法·机器人·ros·slam·激光雷达
艾为电子6 小时前
【技术帖】让接口不再短命:艾为 C-Shielding™ Type-C智能水汽防护技术解析
c语言·开发语言
weixin_413063216 小时前
记录 MeshFlow-Online-Video-Stabilization 在线稳像
算法·meshflow·实时防抖
会编程的土豆6 小时前
【数据结构与算法】动态规划
数据结构·c++·算法·leetcode·代理模式
炘爚7 小时前
深入解析printf缓冲区与fork进程复制机制
linux·运维·算法