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?
题意:有N个小孩子站成一行,每一个人有一个权重,然后给他们发糖果。发糖果需要满足以下条件:
- 每一个小孩必须有一个糖果
- 权重更高的小孩糖果应该比他们旁边的小孩要多
求最少需要多少糖果
思路:首先有一种发糖果的情况是可以确定分配方法的:到第i个小孩,权重条形图呈非递减状。
即:
- 如果i+1个小孩的权值大于i个小孩,那么i+1个小孩的糖果数量为i个小孩的数量+1
- 如果i+1个小孩的权值等于i个小孩,i+1个小孩的糖果数量为1(暂时假设i+1为最后一个小孩)
也就是说,唯一需要讨论的情况就是:i+1个小孩的权值小于i个小孩(同理i个小孩的权值与i+j个小孩相等([i+1,i+j],j>1),i+j+1个小孩权值小于i个小孩)
在这种情况下,影响i个小孩能得到的糖果数量是i+1个小孩的糖果数量,因为i个小孩的权值比i+1个小孩大,使得i+1个小孩的糖果数量要比i个小孩多。此外,由于[0,i-1]个小孩我们假设是非降序序列,因此i个小孩的糖果数量又应该比i-1个小孩要多。
也就是说,当区间[i,j]中的小孩权值呈凸形图(即有中间是顶峰,两边递减),顶峰对应的小孩能得到的糖果数量受左右小孩糖果数量的影响。这样就可以设计式子计算了。
代码:
public class Solution {
public int candy(int[] ratings) {
if(ratings == null || ratings.length == 0){
return 0;
}
int res = 1;
int prev = 1;
int desLength = 0;
for(int i = 1; i < ratings.length; i++){
if(ratings[i] >= ratings[i - 1]){
if(desLength > 0){
res += desLength * (desLength + 1) / 2;
if(desLength >= prev){
res += desLength - prev + 1;
}
prev = 1;
desLength = 0;
}
prev = ratings[i] == ratings[i - 1] ? 1 : prev + 1;
res += prev;
} else {
desLength++;
}
}
if(desLength > 0){
res += desLength * (desLength + 1) / 2;
if(desLength >= prev){
res += desLength - prev + 1;
}
}
return res;
}
}