- Candy
problem:
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?
Example 1:
Input: [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
Example 2:
Input: [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
The third child gets 1 candy because it satisfies the above two conditions.
这道题是根据数组ratings的值,比左或右邻居值大的就要比邻居多分糖果(局部最大值)
思路进化:
刚开始想的是每个元素和左右比较,比任意一个大就candy+1
分配一个candy数组,赋每个元素初始值为1,满足了条件每个人至少一颗糖
待改进思路1):
数组每个值都要左右比,比如i和[i-1]以及[i+1]比
但是看到没有,i和i+1比了之后,再到i+1的时候,还需要和左边的i比吗,不需要,因为刚才在i的时候它们俩已经比过了,所以用一个larger的boolean值记录下i和右边的i+1的比较结果,i+1比较大的话就是larger=true,到i+1的时候,看到larger就知道和左边i的比较结果。
那么只需要一路向右比较,ratings[i]比ratings[i+1]大, candy[i]就+1, ratings[i]比ratings[i+1]小,就candy[i+1]+1
但是这种情况有个问题,比如
ratings: 1,2,32,32
candy 1,1, 1 , 1, 然后会变成下面,就是连续增大的情况会区分不出
1,2, 2, 1
待改进思路2):
针对这个问题,把以上思路(ratings[i]比ratings[i+1]大, candy[i]就+1, ratings[i]比ratings[i+1]小,就ratings[i+1]+1)换成ratings[i]比ratings[i+1]大, candy[i]=candy[i+1]+1, ratings[i]比ratings[i+1]小,就candy[i+1]=candy[i] + 1
这个思路会出现什么问题,还是上面的例子
ratings: 1, 2, 32, 32, 2, 1
candy 1, 1, 1 , 1, 1, 1
(step1) 1, 2, 1, 1 , 1, 1
(step2) 1, 2, 3, 1, 1, 1
(step3) 1, 2, 3, 2, 2, 1
这时候右边出问题,因为和右边比较加了自身的值以后不能保证自己左边的值的正确性
最后一个32那里实行candy[3] = candy[4]+1的时候,2对应的candy[4]还是1,但是走到2的时候,candy[4]变成了2,这个时候左边的没有更新,就出现了问题
改进后思路:
为防止走下一步时值又更新的情况,如上,所以思路变成先一路向右更新一个方向,再一路向左更新反方向
从左到右:ratings[i] > ratings[i-1] then candy[i] = candy[i-1]+1
从右到左:ratings[i] > ratings[i+1] then candy[i] = candy[i+1]+1
发现问题没有,右到左,比如
ratings: 1, 2, 5, 6, 2
candy: 1, 2, 3, 4, 1 (左到右)
1,2, 3, 5, 1 (右到左)
可以看出倒数第二个元素加了两次, 这时候就需要在右到左加一个条件
ratings[i] > ratings[i+1] && candy[i] <= candy[i+1]
就是说如果i的糖果已经比i+1多了,就不需要再加了
代码:
public int candy(int[] ratings) {
int sum = 0;
int[] candy = new int[ratings.length];
Arrays.fill(candy, 1);
for(int i = 1; i < ratings.length; i++) {
if(ratings[i] > ratings[i-1]) {
candy[i] = candy[i-1] + 1;
}
}
sum += candy[ratings.length-1];
for(int i = ratings.length-2; i >= 0; i--) {
if(ratings[i] > ratings[i+1] && candy[i] <= candy[i+1]) {
candy[i] = candy[i+1] + 1;
}
sum += candy[i];
}
return sum;
}