Candy - LeetCode
题目:
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:
1.Each child must have at least one candy.
2.Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?
分糖只有两个要求,每个小朋友至少要有1颗糖,并且rating高的小朋友所得得到的糖要比站在他旁边的,rating比他低的小朋友多。
那么可以得到的信息:
如果一个小朋友的两边站的都是rating比他高的小朋友,那么只需要给他只给1颗糖
如果他旁边站着rating比他低的小朋友A,那么需要给他A小朋友所得糖数+1颗糖
如果他旁边站着的rating和他一样的小朋友,,这个题目里没说清楚,需要踩一下坑才知道什么情况
下面来说一下我的2B方法:
做题的时候可以逐个考虑(整体的方法我也想过,貌似不太方便),先从左边的小朋友开始给
(以下用v[k]来表示第k个小朋友得到的糖数,r[k]代表第k个小朋友的rating,共n个小朋友)
- 给第0个小朋友1颗糖, 令k=1
- 如果第k个小朋友的rating比第k-1个小朋友高,那么给他v[k-1]+1颗糖; 如果第k个小朋友的rating和第k-1个小朋友一样,那么给他1颗糖(踩完坑才知道只要给1颗); 如果第k个小朋友的rating比第k-1个小朋友低,那么给他1颗糖,令j = k,并跳到步骤4。
- k += 1。如果k < n跳到步骤2;如果k == n结束
- 如果r[j-1] <= r[j]或者v[j-1] > v[j],跳到步骤3;如果v[j-1] == v[j]并且r[j-1] > r[j],那么v[j-1] ++ ,j–,跳到步骤4(注:这里不可能出现v[j-1] < v[j]并且r[j-1]>r[j]的情况,因为执行完步骤3后,对任意k,v[k-1]都是大于v[k]的,所以即使v[k]加了1,最多也只能和v[k-1]相等,而不会大于)
class Solution {
public:
int candy(vector<int>& ratings) {
if (ratings[ratings.size()-1] < ratings[0])
reverse(ratings.begin(),ratings.end());
vector<int> v;
v.assign(ratings.size(), 0);
for (int i = 0; i < ratings.size(); i++) {
if (i == 0) v[i]++;
else {
if (ratings[i] > ratings[i-1]) {
v[i] = v[i-1]+1;
} else if (ratings[i] == ratings[i-1]) {
v[i] = 1;
} else {
v[i] = 1;
if (v[i-1] == 1) {
for (int j = i-1; j >= 0; j--) {
if (ratings[j] > ratings[j+1] && v[j] == v[j+1]) {
v[j]++;
} else if (ratings[j] <= ratings[j+1]) {
break;
}
}
}
}
}
}
int sum = 0;
for (int i = 0; i < v.size(); i++) {
sum += v[i];
}
return sum;
}
};
写完后看了下别人的代码,再一次觉得自己蠢爆。我的方法是每给一个小朋友发完糖,就回头检查一遍满不足满足条件,不满足就调整。人家的方法是先从左往右发糖,整个过程中始终满足如果r[k-1] < r[k]就有v[k-1] < v[k],如果r[k-1] >= r[k],那么v[k] = 1,遍历完之后,再从右往左调整。
class Solution {
public:
int candy(vector<int>& ratings) {
int len = ratings.size(), res = 0, i;
if(len>0)
{
vector<int> number(len,0); // to save the number of candies for child[0:N-1]
number[0] = 1;
// forward scan to calculate how many candies needed for child i to make sure it has more candies than its left neighbor if it has a higher rate, otherwise, give one candy to it
for(i=1; i<len;++i) number[i] = ratings[i]>ratings[i-1]?number[i-1]+1:1;
// backward scan to calculate to make sure child i has more candies than its right neighbor if it has a higher rate, pick the bigger one from forward and backward scans as the final number for child i
for(i=len-2, res = number[len-1]; i>=0;--i)
{
if( (ratings[i]>ratings[i+1]) && number[i]<(number[i+1]+1) ) number[i] = number[i+1]+1;
res += number[i];
}
}
return res;
}
};