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?
如果rank比邻居的要大,分到的糖果数量也应该比邻居的多,先找一个简单的例子看看规律:
rank | 6 | 1 | 4 | 8 | 5 | 3 | 6 |
candy | 2 | 1 | 2 | 3 | 2 | 1 | 2 |
初步来看,应该和连续的升序列有关,因为一段连续的升序列,分配的糖果必然要越来越多。
按照以上原则,只考虑升序列,把整个rank按照升序列划分来分糖果看看:
rank | 2 | 3 | 9 | 4 | 6 | 2 | 1 | 4 | 8 | 6 |
candy | 1 | 2 | 3 | 1 | 2 | 1 | 1 | 2 | 3 | 1 |
很明显不正确,红色部分不满足要求,增为2之后仍然不满足
为什么呢,因为这里构成了一个连续的降序列了,降序列逆着考虑也要保证糖果递增的。
到这里清楚了,应该同时考虑连续的升序列和降序列,取他们需要分得糖果的最大值。
如果相邻的rank一样怎么处理呢,第一种当做连续序列的一部分,也就是考虑【不降】或【不升】序列。
第二种是考虑严格的升、降序列。对比一下就很明显了,应该考虑严格的升、降序列。
rank | 1 | 5 | 5 | 5 | 6 | 2 | 6 | 9 | 4 |
candy | 1 | 2 | 2 | 2 | 3 | 1 | 2 | 3 | 1 |
candy | 1 | 2 | 1 | 1 | 2 | 1 | 2 | 3 | 1 |
public static int candy(int[] ratings)
{
int len=ratings.length;
int sum=0;
int start=0;
int end=0;
int[] ascend=new int[len];
int[] descend=new int[len];
while(start<len)
{
int cnt=1;
for(end=start;end<len-1;)
if(ratings[end]<ratings[end+1])
{
ascend[end]=cnt;
cnt++;
end++;
}
else {
break;
}
ascend[end]=cnt;
start=end+1;
}
start=end=len-1;
while(start>=0)
{
int cnt=1;
for(end=start;end>0;)
if(ratings[end]<ratings[end-1])
{
descend[end]=cnt;
cnt++;
end--;
}
else {
break;
}
descend[end]=cnt;
start=end-1;
}
for(int i=0;i<len;i++)
sum+=Math.max(ascend[i], descend[i]);
return sum;
}