分发糖果
难度:
标签:
题目描述
n
个孩子站成一排。给你一个整数数组 ratings
表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
- 每个孩子至少分配到
1
个糖果。 - 相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
示例 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 * 104
0 <= ratings[i] <= 2 * 104
代码结果
运行时间: 32 ms, 内存: 18.2 MB
/*
* 思路:
* 1. 首先初始化每个孩子至少得到1个糖果。
* 2. 从左到右遍历,如果右边的孩子评分比左边的高,右边孩子的糖果数为左边孩子糖果数加1。
* 3. 从右到左遍历,如果左边的孩子评分比右边的高,左边孩子的糖果数为右边孩子糖果数加1。
* 4. 使用Java Stream返回所有孩子糖果数的总和。
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public int candy(int[] ratings) {
int n = ratings.length;
int[] candies = new int[n];
Arrays.fill(candies, 1);
// 从左到右遍历
IntStream.range(1, n).forEach(i -> {
if (ratings[i] > ratings[i - 1]) {
candies[i] = candies[i - 1] + 1;
}
});
// 从右到左遍历
IntStream.iterate(n - 2, i -> i >= 0, i -> i - 1).forEach(i -> {
if (ratings[i] > ratings[i + 1]) {
candies[i] = Math.max(candies[i], candies[i + 1] + 1);
}
});
// 计算总糖果数
return Arrays.stream(candies).sum();
}
}
解释
方法:
该题解采用了两次遍历的方式来分配糖果。首先从左到右遍历,保证相邻两个孩子中评分更高的孩子获得更多的糖果。然后从右到左遍历,再次保证相邻两个孩子中评分更高的孩子获得更多的糖果,同时不破坏之前的分配。最后计算总共需要的糖果数目。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在解决这个问题时需要两次遍历(一次从左到右,一次从右到左),单次遍历是否能够满足题目要求?
▷🦆
在第二次遍历过程中,使用`max`函数来更新糖果数的原理是什么?这样做为何能保证不破坏第一次遍历的结果?
▷🦆
算法中初始化所有孩子的糖果数为1的依据是什么?这一步是否有可能导致某些情况下的糖果分配不公平?
▷🦆
如果数组`ratings`是单调递增或递减的,这种双遍历方法的效率如何?是否有更优的方法?
▷