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

相关推荐
Gust of wind12 分钟前
串与KMP模式匹配:存储结构、基本操作、next数组手算
c语言·数据结构·后端·算法
Navigator_Z18 分钟前
LeetCode //C - 1283. Find the Smallest Divisor Given a Threshold
c语言·算法·leetcode
by2099937 分钟前
list:迭代器与资源管理实现的综合叙述(下)
数据结构·c++·笔记·list
啦啦啦啦啦zzzz1 小时前
一致性哈希
服务器·算法·哈希算法·c++20·分布式存储
我不会起名字3221 小时前
二叉树的遍历与二叉搜索树:把递归、迭代、还原树一次讲透
数据结构·leetcode·二叉树·二叉搜索树
垆边人似月.1 小时前
嵌入式传感器寄存器数据解析
算法
Tingmanyi1 小时前
YOLOv13改进策略【卷积层篇】| RFAConv 感受野注意力卷积,每个位置都值得被单独加权
深度学习·算法·yolo·目标检测·计算机视觉
yi0112 小时前
Leetcode 49 用 “身份证‘‘巧解
人工智能·笔记·python·算法·leetcode·哈希表
liuchangng2 小时前
类Jev项目Kev从入门到实战(7):如何选型:决策树与 checklist
算法·决策树·机器学习
yi0112 小时前
DAY22: LeetCode 733:图像渲染——从二维网格开始理解 DFS 和 BFS
数据结构·笔记·python·算法·leetcode·深度优先·宽度优先