Candy
There areNchildren 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?
这道题的关键:还是审题。感觉LeetCode的题目审题都难没审清楚题目就做,往往非常浪费时间。
还是列子最好说明问题:
比如我一开始考虑:1 2 3 3 3这样应该结果是 12,但是其实要求是8.
1 2 3 2 3 我以为结果是11,但是其实要求是9.
都看懂意思了吧。他这个要求其实是把题目”简化“了,反而害我们想多了的多做功夫了。
弄清楚题目之后就好办了。
下面是第一种解法:
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
int candy(vector<int> &ratings) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(ratings.empty()) return 0;
int n = ratings.size();
vector<int> candyNum(n);
//这里不能用for(auto x:candyNum) x=1;这样无法修改candyNum的值的。
for(int i=0; i<n; i++)
{
candyNum[i] = 1;
}
for(int i=1; i<n; i++)
{
if(ratings[i-1]<ratings[i])
candyNum[i] = candyNum[i-1]+1;
}
for(int i=n-2; i>=0; i--)
{
if(ratings[i+1]<ratings[i] && candyNum[i]<(candyNum[i+1]+1))
candyNum[i] = candyNum[i+1]+1;
}
int sum = 0;
for(int i=0; i<n; i++)
sum += candyNum[i];
return sum;
}
};
int main()
{
int a[] = {1,2,3,3,3};
vector<int> va(a, a+5);
Solution solu;
cout<<solu.candy(va)<<endl;
return 0;
}
其实vector创建的时候就已经为零的了,了解了这个属性之后可以省去第一个赋值循环,然后稍微改进一点,如下:
class Solution {
public:
int candy(vector<int> &ratings) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(ratings.empty()) return 0;
int n = ratings.size();
//利用vector属性,初始化为零
vector<int> candyNum(n,0);
for(int i=1; i<n; i++)
{
if(ratings[i-1]<ratings[i])
candyNum[i] = candyNum[i-1]+1;
}
for(int i=n-2; i>=0; i--)
{
if(ratings[i+1]<ratings[i] && candyNum[i]<(candyNum[i+1]+1))
candyNum[i] = candyNum[i+1]+1;
}
int sum = 0;
for(int i=0; i<n; i++)
sum += candyNum[i] + 1;
//利用vector属性,初始化元素为零,candyNum存储的数量比实际数量少1,所以加1
return sum;
}
};
下面就用一个循环,不过嵌套了中间循环,也正因为这样,所以效率比较低,没accepted。不过也是不错的想法,所以贴出来分享下:
struct twoInt {
int left;
int right;
twoInt():left(1),right(1){}
};
class Solution {
public:
int candy(vector<int> &ratings) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(ratings.empty()) return 0;
int n = ratings.size();
vector<twoInt> candyNum(n);
for(int i=0; i<n; i++)
{
for(int k=i; k<n-1; k++)
{
if(ratings[k]<=ratings[k+1])
break;
candyNum[i].right++;
}
for(int k=i; k>0; k--)
{
if(ratings[k]<=ratings[k-1])
break;
candyNum[i].left++;
}
candyNum[i].left =
candyNum[i].left>=candyNum[i].right ? candyNum[i].left : candyNum[i].right;
}
int sum = 0;
for(int i=0; i<n; i++)
sum += candyNum[i].left;
return sum;
}
};
总结:
做LeetCode注重审题啊,这个是做出来的经验。而且不知道LeetCode是否是故意的,题目都不啰嗦,输出列子也不多给,读者没认真读懂题目是读者的责任了。
更新很简洁的程序,终极版本了,没法继续清晰和简洁了。
//2014-2-18 update
int candy(vector<int> &ratings)
{
int *A = new int[ratings.size()];
A[0] = 1;
for (int i = 1; i < ratings.size(); i++)
{
if (ratings[i] > ratings[i-1]) A[i] = A[i-1]+1;
else A[i] = 1;
}
int ans = A[ratings.size()-1];
for (int i = ratings.size() - 2; i >= 0 ; i--)
{
if (ratings[i] > ratings[i+1]) A[i] = max(A[i], A[i+1]+1);
ans += A[i];
}
return ans;
}