这个函数使用两次遍历来满足题目的条件,第一次从左到右分配糖果,第二次从右到左确保右边高评分的孩子分配更多的糖果。最后,返回总糖果数量作为结果。
为什么用左右两次遍历:
首先,第一次遍历从左到右分配糖果,确保了每个孩子至少获得一个糖果。这是因为在第一次遍历中,如果一个孩子的评分比前一个孩子高,那么它会获得多于前一个孩子的糖果。如果评分相同,它将获得一个糖果。这确保了每个孩子至少有一个糖果。
然后,第二次遍历从右到左,它是为了确保右边高评分的孩子获得更多的糖果。在第一次遍历中,我们只考虑了从左到右的关系,但第二次遍历允许我们修正任何在第一次遍历中可能未满足的条件。
综合考虑两次遍历,可以确保两个条件同时满足:每个孩子至少获得一个糖果,以及如果一个孩子的评分高于其相邻的孩子,那么他将获得更多的糖果。这就是为什么使用两次遍历的正确性。
int candy(int* ratings, int ratingsSize) {
// 创建一个数组,用于存储每个孩子分配的糖果数量
int arr[ratingsSize];
int i;
// 初始化第一个孩子的糖果数量为1
arr[0] = 1;
// 第一遍扫描,从左到右分配糖果
for (i = 0; i < ratingsSize - 1; i++) {
if (ratings[i] < ratings[i + 1]) {
// 如果当前孩子的评分比下一个孩子高,分配更多的糖果
arr[i + 1] = 1 + arr[i];
} else if (ratings[i] > ratings[i + 1]) {
// 如果当前孩子的评分比下一个孩子低,分配1个糖果
arr[i + 1] = 1;
// 如果前一个孩子只有1个糖果,为了满足题目条件,给前一个孩子再加1个糖果
if (arr[i] == 1)
arr[i] = 2;
} else {
// 如果两个孩子评分相同,分配1个糖果
arr[i + 1] = 1;
}
}
// 第二遍扫描,从右到左,确保满足右边高评分的孩子分配更多糖果的条件
for (i = ratingsSize - 1; i > 0; i--) {
if (ratings[i] < ratings[i - 1]) {
// 如果当前孩子的评分比前一个孩子低,并且当前孩子的糖果数量大于等于前一个孩子的,给前一个孩子加1个糖果
if (arr[i] >= arr[i - 1])
arr[i - 1] = arr[i] + 1;
}
}
// 计算总糖果数量
int num = 0;
for (i = 0; i < ratingsSize; i++)
num += arr[i];
// 返回总糖果数量
return num;
}