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?
解法一:使用贪心算法,先从左到右扫一次,如果ratings[i+1]>ratings[i],那么i+1获得的糖果就比i多一个。若ratings[i+1]小于或者等于ratings[i],则先默认获得一个糖果,先不管具体的值,然后从尾到头再使用一次贪心,如果ratings[i-1]>ratings[i],则i-1获得的糖果数是i获得的糖果数加1和之前那次贪心留下来的值比较,取最大值。最后将sum求和则解出。
代码
class Solution {
public:
int candy(vector<int>& ratings) {
int a[ratings.size()]={0};
if(ratings.size()==1)
return 1;
for(int i=0;i<ratings.size();i++)
a[i]=1;
int n=ratings.size();
for(int i=0;i<n-1;i++)
{
if(ratings[i+1]>ratings[i])
{
a[i+1]=a[i]+1;
}
}
for(int i=n-1;i>0;i--)
{
if(ratings[i-1]>ratings[i])
{
a[i-1]=max(a[i]+1,a[i-1]);
}
}
int sum=0;
for(int i=0;i<ratings.size();i++)
{
sum+=a[i];
}
return sum;
}
};
解法二:
由于ratings一定是由非递增数列和非递减数列组成的,若一部分为递增,那么获得的糖果数一定是1,2,3……X,若为递减,则一定是X……3,2,1,如果一个数左边为递增,右边递减,则他应为两边中取较大的一个数。如果相等,则后一个糖果数取默认值为1.
代码:
class Solution {
public:
int candy(vector<int>& ratings) {
int a[ratings.size()];
a[0]=1;
int candynum=1;
if(ratings.size()==1)
return 1;
int sum=0;
int n=ratings.size();
for(int i=0;i<ratings.size()-1;)
{
if(ratings[i+1]>ratings[i])
{
for(i;i<n-1&&ratings[i+1]>ratings[i];i++)
sum+=candynum++;
}
else if(ratings[i]==ratings[i+1])
{
sum+=candynum;
i++;
candynum=1;
}
else
{
int d=1;
for(i;i<n-1&&ratings[i+1]<ratings[i];i++)
{
sum+=d++;
}
sum+=max(d,candynum);
candynum=1;sum--;
}
}
sum+=candynum;
return sum;
}
};
做完遗留的小问题:
第二种算法参考了http://blog.csdn.net/peerlessbloom/article/details/39735575的文章解题思路,虽然觉得第二种方法只遍历了一次vector,但他用时53ms比第一种的36ms还要长,不知道什么原因。