n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目
第一次尝试
看到这个题目,我们首先想到的就是从左往右依次遍历,然后看它是不是比旁边两个孩子的分数高,如果分高就多发一个糖果,最后发的糖果量再加上孩子的总数量即可满足题目要求,代码如下:
int candy(int* ratings, int ratingsSize)
{
int CandyNum = 0; //多发的糖果数量
for(int i = 0; i< ratingsSize; i++)
{
//从0开始,到孩子数量减1结束,不计算最后一位,因为最后一位无下一位
if(i >= 0 && i < ratingsSize - 1 && ratings[i] > ratings[i + 1])
CandyNum++; //如果当前分数比下一个孩子分数高,则糖果+1
//从1开始,到孩子数量结束,不计算第0位,因为第0位无上一位
if(i > 0 && i < ratingsSize && ratings[i] > ratings[i - 1])
CandyNum++; //如果当前分数比前一个分数高,则糖果+1
}
return CandyNum + ratingsSize; //返回多发的糖果数量+孩子总数
}
再看运行结果:
造成这种差别的原因是第1个孩子分数为3,比旁边两位都高所以要多发2个糖果,但是题目要求返回最少的糖果数量,也就是说第0个孩子多发0个糖果,第1个孩子比第0个孩子高,多发1个糖果,比第2个孩子分数高,再多发1个糖果。此时重复了1个糖果,因为第1个孩子只需多发1个糖果,就可以满足比第0个孩子和第2个孩子糖果都多,因此我们需要把重复的糖果数量减去,代码如下:
int candy(int* ratings, int ratingsSize)
{
int CandyNum = 0, GiveCandytimes = 0, RepeatCandy = 0;
for(int i = 0; i< ratingsSize; i++)
{
if(i >= 0 && i < ratingsSize - 1 && ratings[i] > ratings[i + 1])
{
CandyNum++;
//如果满足条件,给糖果次数加一
GiveCandytimes++;
}
if(i > 0 && i < ratingsSize && ratings[i] > ratings[i - 1])
{
CandyNum++;
//如果满足条件,给糖果次数+1
GiveCandytimes++;
}
//如果给糖果次数为2表示重复给1次,重复次数+1
if(GiveCandytimes == 2)
RepeatCandy++;
//给糖果次数清零,方便下一次循环
GiveCandytimes = 0;
}
//返回给糖果总数+孩子数量-重复给的糖果
return CandyNum + ratingsSize - RepeatCandy;
}
再看运行结果:
此时对于这个数组,又少发了两个糖果,原因是动态比较的问题,第1个孩子比第0个孩子分高,多发1个,第2个孩子比第1个孩子多,也是多发一个,但是题目要求相邻两个孩子分高的获得更多的糖果,因此第2个孩子要比第一个孩子还多,也就是多发两个,右边同理,此时要对代码进行改进,以保证要对糖果分配进行动态规划
我们可以从左往右依次遍历,如果下一个孩子分数比当前孩子高,就把下一个孩子的糖果数量用当前孩子的糖果数量+1,同理再从右往左依次遍历,原理一样,这样就实现了动态规划糖果
代码如下:
int candy(int* ratings, int ratingsSize)
{
int GiveCandys = 0;
//分配内存
int *GiveCandy = (int *)malloc(ratingsSize * sizeof(int));
GiveCandy[0] = 1; //第0位给1个糖果
for(int i = 0; i< ratingsSize - 1; i++)
{
GiveCandy[i + 1] = 1; //下一位给1个糖果
if(ratings[i] < ratings[i + 1])
//如果满足条件,下一位的糖果数量等于当前糖果数量+1
GiveCandy[i + 1] = GiveCandy[i] + 1;
}
for(int i = ratingsSize - 1; i > 0; i--)
{
if(ratings[i] < ratings[i - 1] && GiveCandy[i] >= GiveCandy[i - 1])
//如果满足条件,上一位的糖果数量等于当前糖果数量+1
GiveCandy[i - 1] = GiveCandy[i] + 1;
}
//遍历一遍计算糖果总数
for(int i = 0; i < ratingsSize; i++)
GiveCandys += GiveCandy[i];
//返回糖果总数
return GiveCandys;
}
再看输出结果: