题目描述
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.
题解
最近实在太忙,没有时间整块去搞AI的系统学习,只能零碎时间刷刷题。这道题其实我最初碰到是当年去Airbnb面试,当时拿到的是二维的9宫格,其他条件类似,当时非常可惜,但是35分钟之呢,代码没有写好,也错过了心仪的offer。现在看来,这个题的解法其实是很发散的。 对于一维的分糖果问题来说,其实最大的坑点在于遍历的时候,遇到相等序列和下降序列,到底减少多少糖果为适宜。
昨天初刷这道题的时候,我用了一个非常傻但是直接的想法,即两趟遍历,第一趟维持第一个人一个糖果,右边比他高,就加一个,遇到相等和下降,就直接置1,继续之前策略。第二遍,反方向,初始置0,前进遇到高的就加1。 这里我一开始一直没有ac的原因是,其实不是盲目的加1,而是应该判断,当前增加后的糖果数,是不是比第一轮的值大,大了加上增量就好,反之,不用加上。下面贴上代码:
class Solution {
public:
int candy(vector<int>& ratings) {
int len = ratings.size();
if (len == 0) return 0;
if (len == 1) return 1;
int cur = 1;
int sum = 1;
map<int,int> score;
score[0] = 1;
for(int i=1;i<len;i++){
if(ratings[i]>ratings[i-1]){
cur+=1;
sum+=cur;
score[i] = cur;
}else{
cur = 1;
sum+=cur;
score[i] = cur;
}
}
cur = 0;
for(int i=len-2;i>=0;i--){
if(ratings[i]>ratings[i+1]){
cur+=1;
if(score[i] < 1 + cur){
sum+=(1+cur - score[i]);
}else{
cur = 0;
}
}else{
cur = 0;
}
}
return sum;
}
};
后来仔细想想,代码可以在优化一下,第二轮的时候,直接比较相邻的有增加的两项就好,代码如下:
class Solution {
public:
int candy(vector<int>& ratings) {
int len = ratings.size();
vector<int> candy_nums(len,1);
int sum = 0;
for(int i=0;i<len-1;i++){
if(ratings[i+1]>ratings[i]){
candy_nums [i+1] = candy_nums[i]+1;
}
}
for(int i = len-1;i>0;i--){
if(ratings[i-1]>ratings[i]){
candy_nums [i-1] = max(candy_nums[i-1],candy_nums[i]+1);
}
}
for(auto num:candy_nums){
sum+=num;
}
return sum;
}
};
当然可以继续优化,一趟遍历搞定。其实我当初还有个趣味的思路,即把rating值的差异,当做偏序关系,构建有向边,然后利用拓补排序搞定。而且我觉得这个做法,在二维中可能比两遍遍历更加的简单。待我有空,一一补充。