1. 问题背景与核心挑战
LeetCode 135题"分发糖果"是一个经典的贪心算法应用题,它模拟了现实中按表现分配奖励的场景。题目要求为一排孩子分配糖果,每个孩子至少得到一个糖果,且相邻孩子中评分更高的必须获得更多糖果。我们的目标是在满足这两个约束条件下,找出总糖果数最少的分配方案。
这个问题的难点在于约束条件的双向性。传统的单向贪心策略(如从左到右扫描)无法同时满足"左邻居"和"右邻居"的双向比较要求。举个例子,当评分序列为[1,3,2,1]时:
- 第一个孩子得1颗
- 第二个孩子(3)比左边高,得2颗
- 第三个孩子(2)比左边低,理论上得1颗,但这会导致它比右边的1分孩子糖果数相同,违反规则
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法设计思路解析
2.1 双向扫描策略
解决这个问题的关键在于将双向约束拆解为两个单向处理:
- 从左到右扫描,确保每个孩子比左边评分高的邻居得到更多糖果
- 从右到左扫描,确保每个孩子比右边评分高的邻居得到更多糖果
- 对每个位置取两次扫描结果的较大值
这种分治思想将复杂问题简化为两个可独立处理的子问题。在第一次扫描时,我们只需要关注左侧约束;第二次扫描则专注于右侧约束。最终的分配方案就是同时满足两个约束的最小解。
2.2 贪心选择的正确性证明
为什么这种方法能得到最优解?可以从以下角度理解:
- 单向扫描得到的已经是该方向上的最小解
- 取最大值操作保证了两个约束同时满足
- 任何更小的分配都会至少违反一个方向的约束
用数学归纳法可以严格证明:假设前i-1个孩子已正确分配,那么第i个孩子的分配数只可能由左侧或右侧的较大约束决定,这正是贪心选择的最优子结构性质。
3. 详细实现步骤
3.1 初始化阶段
python复制def candy(ratings):
n = len(ratings)
left = [1] * n # 从左到右的分配数组
right = [1] * n # 从右到左的分配数组
每个孩子初始分配1颗糖果,这是满足"每人至少一颗"的基础条件。创建两个数组分别记录两个方向的分配结果。
3.2 左扫描处理
python复制for i in range(1, n):
if ratings[i] > ratings
