LeetCode 135. 分发糖果
题目描述


题意分析
给一排孩子分配糖果,每人至少一颗。若某个孩子的评分高于紧邻的孩子,他的糖果数也必须更多;只比较相邻位置,不要求评分更高的人比所有低分孩子都拿得多。
相邻评分相等时没有糖果数量的大小关系限制。要求满足所有这些条件,并使总糖果数最少,不能只找到一种可行分配。
解法:左右两次扫描取最大约束
核心思路
[!blue]
一个孩子可能同时受到左右两边的限制。先分别求出只考虑左邻居、只考虑右邻居时的最低需求,再取足以满足两边的较大值,就能把相互牵连的要求拆开。
从左到右扫描时,左邻居的需求已经确定。若当前评分更高,当前至少要比左边多一颗,令
candies[i] = candies[i - 1] + 1;否则左侧没有额外要求,保留最初的一颗。这给出了每个位置由连续上升段产生的必要下界。再从右到左处理右侧限制。若当前评分高于右邻居,它至少需要
candies[i + 1] + 1颗;但第一次扫描已有的左侧下界不能丢,因此取原值与这个需求的最大值。右邻居已在本趟处理完,下降段的要求便能逐个向左传递。为什么这样已经最少?任何合法方案都不能低于任一方向算出的下界,而取较大值没有额外增加不需要的糖果。它也确实可行:上升相邻对由左扫保证,下降相邻对由右扫保证;右扫只会为“左边评分更高”的相邻对增加左边的糖果,不会破坏该对要求,若再影响更左边,则下一轮会继续补足。
因此两次扫描结束后,每个位置都达到同时满足左右约束的最低值,求和就是最少总数。
解题步骤
- 建立与评分数组等长的
candies,全部初始化为1,满足每人至少一颗。- 从第二个孩子向右扫描,当前评分高于左邻居时,把当前糖果数设为左邻居加一。
- 从倒数第二个孩子向左扫描,当前评分高于右邻居时,取当前糖果数与右邻居加一中的较大值。
- 相等评分不触发任何一侧的增加,最后累加全部糖果数并返回。
代码实现
class Solution {
public int candy(int[] ratings) {
int n = ratings.length;
int[] candies = new int[n];
Arrays.fill(candies, 1);
for (int i = 1; i < n; i++) {
if (ratings[i] > ratings[i - 1]) {
candies[i] = candies[i - 1] + 1;
}
}
for (int i = n - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1]) {
// 同时满足左侧扫描和右侧扫描给出的最小约束。
candies[i] = Math.max(candies[i], candies[i + 1] + 1);
}
}
int ans = 0;
for (int candy : candies) {
ans += candy;
}
return ans;
}
}
func candy(ratings []int) int {
n := len(ratings)
candies := make([]int, n)
for i := 0; i < n; i++ {
candies[i] = 1
}
for i := 1; i < n; i++ {
if ratings[i] > ratings[i-1] {
candies[i] = candies[i-1] + 1
}
}
for i := n - 2; i >= 0; i-- {
if ratings[i] > ratings[i+1] {
needed := candies[i+1] + 1
// 保留左侧约束与右侧约束中的较大者,不能覆盖已经满足的要求。
if candies[i] < needed {
candies[i] = needed
}
}
}
ans := 0
for _, candy := range candies {
ans += candy
}
return ans
}
复杂度分析
- 时间复杂度:$O(n)$,两次扫描和一次求和都为线性时间。
- 空间复杂度:$O(n)$,使用一个与评分数组等长的糖果数组。
关键点总结
[!green]
- 两遍扫描分别传播左侧和右侧的必要下界,方向必须与依赖方向一致。
- 第二遍用最大值合并要求,既补足右侧约束,也保留左侧已经确定的下界。
- 严格更高的评分才要求严格更多糖果,相等评分不建立递增关系。
易错点总结
[!yellow]
- 只从左向右扫,会遗漏下降段中左边孩子必须比右边多的要求。
- 右扫直接覆盖原值,可能把由较长上升段决定的峰值降低,破坏左侧约束。
- 第二遍也从左向右走,右邻居尚未计算完整,无法一次正确传播连续下降段的需求。
- 默认糖果数为
0,会违反每人至少一颗的基本条件。- 用
>=触发递增,会给相等评分的孩子增加不必要的糖果,导致结果不再最小。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 42. 接雨水 | 困难 | 同样结合左右两侧约束,本题取两侧糖果最低要求的较大值,接雨水取两侧边界水位的较小值。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!