135 分发糖果
2025年4月29日大约 2 分钟
🚀 相关链接
📜 描述
有 n
个孩子站成一排。给你一个整数数组 ratings
表示每个孩子的评分。你需要按照以下要求,给这些孩子分发糖果:
- 每个孩子至少分配到 1 个糖果。
- 相邻两个孩子中,评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目。
💡 示例
- 输入:
ratings = [1,0,2]
- 输出:
5
- 解释: 你可以分别给第一个、第二个、第三个孩子分发
2
、1
、2
颗糖果。
示例 2
- 输入:
ratings = [1,2,2]
- 输出:
4
- 解释: 你可以分别给第一个、第二个、第三个孩子分发
1
、2
、1
颗糖果。第三个孩子只得到1
颗糖果,这满足题面中的两个条件。
📝 提示
n == ratings.length
1 <= n <= 2 * 10^4
0 <= ratings[i] <= 2 * 10^4
💭 思路
- 两次遍历。
根据相邻两个孩子中,评分更高的孩子会获得更多的糖果。
拆分为左规则
和右规则
。
左规则:当 ratings[i−1] < ratings[i] 时,i 号学生的糖果数量将比 i−1 号孩子的糖果数量多。
右规则:当 ratings[i] > ratings[i+1] 时,i 号学生的糖果数量将比 i+1 号孩子的糖果数量多。
先遍历一次数组,计算出满足左规则时,每个孩子分到的最少糖果数量。然后再遍历一次,计算满足右规则时,每个孩子需要分到的最少糖果数量,则位置i的孩子分到的糖果数量为min(left[i],right[i])。
- 常数空间遍历。
将ratings分为升序序列和降序序列,遵循以下规则:
- 如果当前孩子比前一个孩子评分高,则认为当前处于升序序列中,分发的糖果比前一个孩子多1个。
- 否则就认为当前在降序序列中,直接给当前孩子分1个糖果,同时记录当前降序序列长度,降序序列中前面每个孩子都要再+1个糖果。(即总糖果数加一个降序序列长度)
💻 代码实现
- 两次遍历
public int candy(int[] ratings) {
int[] left = new int[ratings.length];
for (int i = 0; i < ratings.length; i++) {
if (i > 0 && ratings[i] > ratings[i - 1]) {
left[i] = left[i - 1] + 1;
} else {
left[i] = 1;
}
}
int right = 0, sum = 0;
for (int i = ratings.length - 1; i >= 0; i--) {
if (i < ratings.length - 1 && ratings[i] > ratings[i + 1]) {
right++;
} else {
right = 1;
}
sum += Math.max(left[i], right);
}
return sum;
}
- 常数空间遍历
public int candy(int[] ratings) {
int cur = 1, pre = 1, incLen = 1, decLen = 0, sum = 1;
while(cur < ratings.length){
if (ratings[cur] >= ratings[cur -1]){
pre = ratings[cur] == ratings[cur - 1]? 1 : pre + 1;
sum+=pre;
incLen = pre;
decLen = 0;
}else if (ratings[cur] < ratings[cur -1]){
pre = 1;
decLen++;
if (decLen == incLen){
decLen++;
}
sum+=decLen;
}
cur++;
}
return sum;
}