LeetCode/135. 分发糖果

135. 分发糖果

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。

你需要按照以下要求,帮助老师给这些孩子分发糖果:

  • 每个孩子至少分配到 1 个糖果。

  • 评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。

那么这样下来,老师至少需要准备多少颗糖果呢?

示例 1:

1
2
3
输入:[1,0,2]
输出:5
解释:你可以分别给这三个孩子分发 2、1、2 颗糖果。

示例 2:

1
2
3
4
输入:[1,2,2]
输出:4
解释:你可以分别给这三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这已满足上述两个条件。

来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

本题基于贪心策略,这道题不同于分配饼干的问题需要对原数组进行排序,这道题如果排序了就会打乱位次顺序,使得返回结果错误。本题每个孩子至少有一个糖果,而且评分高的孩子分到的糖果要比他两边孩子分到的多,由此可见,当前位置的孩子既取决于他左边所有孩子分配的糖果数,也取决于他右边孩子分配的糖果数,如果使用动态规划的思想需要一次性考虑左右两边的情况,比较难想。转而用贪心策略,可以将过程拆解为两部分,即首先计算从左到右所有孩子分配的糖果数,然后计算从右到左所有孩子分配的糖果数。第一轮从左到右我们只需要考虑当前位置相邻的左边孩子的分数,只要当前分数大于左边相邻孩子分数,当前位置的糖果数就是左边相邻糖果数加一。完成后进行从右向左的遍历,如果当前位置分数小于左边分数,左边位置的糖果数就是当前位置糖果数加一,以此类推,这里需要注意的一个细节就是取左边糖果原始数量和当前位置糖果数加一中的较小值,因为我们要保证使用尽可能少的糖果完成任务。

具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public int candy(int[] ratings) {
int[] candies = new int[ratings.length];
Arrays.fill(candies, 1);

for (int i = 1; i < ratings.length; i++) {
if (ratings[i] > ratings[i - 1]) {
candies[i] = candies[i - 1] + 1;
}
}

for (int i = ratings.length - 1; i > 0; i--) {
if (ratings[i] < ratings[i - 1]) {
candies[i - 1] = Math.max(candies[i - 1], candies[i] + 1);
}
}

int result = 0;
for (int i = 0; i < candies.length; i++) {
result += candies[i];
}

return result;
}
}

Comments