题目:
n
个孩子站成一排。给你一个整数数组 ratings
表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
- 每个孩子至少分配到
1
个糖果。 - 相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
示例 1:
输入:ratings = [1,0,2] 输出:5 解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。
示例 2:
输入:ratings = [1,2,2] 输出:4 解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。 第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。
思考
: 已知分数的个数即为孩子的个数设为n,f(n)表示第n个孩子得的糖果数
将题目抽象为数学函数 即 f(n)>=1;
如果ratings[n]>ratings[n-1],则f(n)>f(n-1),那我们就让f(n)=f(n-1)+1;
根据以上条件,可以写出如下代码;
//第一次 从左向右遍历,右跟左比较;
int n=ratings.size();//n=分数个数
vector<int> data(n);//建立一个长度为n的一个数组data用来存储糖果个数;
int i,sum=0;
data[0]=1;//给第一个同学一个糖果;
for(i=1;i<n;i++){
if(ratings[i]>ratings[i-1])
data[i]=data[i-1]+1;//如果右边的同学比左边的同学分数高,分数高的比分数低的多一个糖果;
else//其实应该再分两种情况 =和<;
//=可以让data[i]=data[i-1];
//<可以让 data[i]=data[i-1]-1;
//但是上述条件只是为了满足分数高的糖果多这个条件;
//却无法保证总和最小,所以干脆让小的糖果数为最小值1;
data[i]=1;
}
好了,既然写到这里 我们来举个例子看看代码是否有什么不完善的地方吧
ep:1 2 1 2 1 2 (分数)
1 2 1 1 1 2 糖果数)
我们发现第一个例子似乎是没有问题的,但是第二个出了点小问题,正确结果应该是2 1 2;
那是因为我们在一开始默认让第一个孩子得到了一个糖果,但是如例子所示,他有可能得到了两个糖果。
我们只让右边跟左边相比较,保证了从左往右看,分数多的糖多,但是相邻是左右都要看。
我们开始第二次遍历,从右往左倒着来,左边的数跟右边比较来保证左边数大的糖多。
只有在左边分数大并且糖少的情况下,让左边的糖比右边多1。
for(i=n-2;i>=0;i--){
if(ratings[i]>ratings[i+1]&&data[i]<=data[i+1])
data[i]=data[i+1]+1;
}
注意:i的取值范围是n-2;因为它要和右边的比,数组的最后一个为n-1,所以只可以取n-2。
完整代码如下:
class Solution {
public:
int candy(vector<int>& ratings) {
int n=ratings.size();
vector<int> data(n);
int i,sum=0;
data[0]=1;
for(i=1;i<n;i++){
if(ratings[i]>ratings[i-1])
data[i]=data[i-1]+1;
else
data[i]=1;
}
for(i=n-2;i>=0;i--){
if(ratings[i]>ratings[i+1]&&data[i]<=data[i+1])
data[i]=data[i+1]+1;
}
for(i=0;i<n;i++)
sum=sum+data[i];
return sum;
}
};
如有错误,敬请指教