Question
There are N children standing in a line. Each child is assigned a rating value.
You are giving candies to these children subjected to the following requirements:
- Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?
根据排名给排成一列的孩子糖块,给较高的排名的孩子比相邻的排名较低的孩子更多的糖块,问最少要给多少糖块。
Analysis
注意如果相邻的孩子排名相同,而题目中没有明确要求此种情况怎么安排,为了使使用的糖块更少,很明显,不能给排名相同的孩子相同数量的糖块。
使用贪心算法,每一步分配的糖块尽可能地少。分配一新数组,用于存储糖块的数量。首先从左到右遍历数组,如果后一项rating大于前一项rating,则后面的孩子要比前面的那个孩子多拿一块糖。如果后面的rating小于或者等于前面的rating,则给后面的那个孩子仅仅1块糖。
遍历结束后,很明显这种分配方法不合理,例如对于排序为1,3,2,1这样的ratings,按照第一步分配完,糖块分配的情况是1,2,1,1。这种分配方式导致第三个同学和第四个同学拿到了相同的糖块数量,明显不对,所以需要对分配情况进行调整。
调整我们要从后往前调,使用贪心算法,使每一步再分配的糖块尽可能小。用一个变量记录当前能分配糖块的最大值,每次遇到一个不合理的情况,则使该变量+1;若回归合理,则使该变量回归1重新计算。
按照这种分析情况,我们使用了一个数组来存储糖块的数量,所以空间繁杂度为 O(n) ;期间遍历了两次数组,所以时间复杂度也是 O(n)
Code
int candy(int* ratings, int ratingsSize) {
if(ratingsSize==0) return 0;
if(ratingsSize==1) return 1;
int* candyArray=(int*)malloc(sizeof(int)*ratingsSize);
for(int i=0;i<=ratingsSize-1;i++){
if(i==0) candyArray[0]=1;
else{
if(ratings[i]>ratings[i-1]){
candyArray[i]=candyArray[i-1]+1;
}
else{
candyArray[i]=1;
}
}
}
int adjust=1;
for(int j=ratingsSize-1;j>=1;j--){
if(ratings[j-1]>ratings[j] && candyArray[j-1]<=adjust){
adjust++;
candyArray[j-1]=adjust;
}
else{
adjust=1;
}
}
int result=0;
for(int i=0;i<=ratingsSize-1;i++){
result=result+candyArray[i];
}
return result;
}