LeetCode | Candy

题目:

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?


思路:

思路1:首先要考虑,题目中没有提到连续两个小孩,当他们的ratings相同时应当如何处理。例如,144321。显然,两个ratings为4的小孩不会拿到相同的candy,并且两者之间没有关系。所以我们可以将ratings相同且相邻的小孩分成两个子队列来考虑。

由于上述过程中, 我们将相等的情况排除了,所以在接下来的讨论中,我们可以知道两个相邻的小孩的情况只可能为大于或者小于的关系。
1) 最简单的情况是k个小孩,他们是连续递增或者递减的关系。则candy总数是(1+k)*k/2。
2)在1)的条件上增加复杂度,k个小孩,先递增再递减。这时候两段都是从个数为1开始发放candy,向中间递推直到遇到最大值。最大值这个位置应当取两段递推的较大值。
3)复杂的情况都能够划分为如上1)与2)的子队列。

因此,我们遍历一遍一个不包含相等ratings的队列来找到所有最小值,这些值都应当取1。接下来,我们取相邻最小值组成依次计算,如3)所述。每个部分按照1),2)的计算方法去发放candy。注,开始与结束的位置需要特殊考虑。

思路2:
首先,每个小孩发一个candy。
然后,从右往左,当ratings递减时依次累加发candy。
最后,从左往右,当ratings递增时依次累加发candy,遇到最高点时注意不要覆盖上一步的数据。
整个过程可以由如下的图示来表示:
LeetCode | Candy_第1张图片

代码:

思路1:
class Solution {
public:
    int count;
    vector ratings;
    int candy(vector &ratings) {
        this->ratings = ratings;
        count=0;
        int begin=0;int end=1;
        while(ratings.size()>end)
        {
            if(ratings[end-1]==ratings[end])
            {
                countBottom(begin,end-1);
                begin=end;
            }
            end++;
        };
        countBottom(begin,end-1);
        //将相邻位置rating相同的队列分割为子队列
        
        return count;
    }
    
    void countBottom(int i, int j)
    {
        if(i==j)
        {
            count+=1;
            return;
        }
        else if(i+1==j)
        {
            count+=3;
            return;
        }
        //数目小于2的情况,一定单调
        
        vector bottom;
        
        for(int cur=i+1;curratings[cur])
            {
                bottom.push_back(cur-2);
            }
            if(ratings[cur-1]>ratings[cur]&&ratings[cur]ratings[cur+1])
            {
                bottom.push_back(cur+1);
            }
            else if(cur == j-1&&ratings[cur]0)
        {
            count+=bottom.size();
            if(bottom[0]==i-1)
            {
                count--;
            }
            if(bottom[bottom.size()-1]==j+1)
            {
                count--;
            }
            //开始与结束为止可能是个无效的位置
            
            for(int i=1;imax)
                        {
                            max=ratings[j];
                            index=j;
                        }
                     }
                     //找到最大值的位置
                     count+=((index-(bottom[i-1]+1))<((bottom[i]-1)-index)?(((bottom[i]-1)-index)+2):((index-(bottom[i-1]+1))+2));
                     //最大值的取值
                     if(index>(bottom[i-1]+1))
                     {
                        count+=((index-(bottom[i-1]+1))*(index-(bottom[i-1]+1)+3)/2);
                     }
                     //最大值的左侧
                     if(index<(bottom[i]-1))
                     {
                         count+=(((bottom[i]-1)-index)*((bottom[i]-1)-index+3)/2);
                     }
                     //最大值的右侧
                }
            }    
        }
    }
};

思路2:
class Solution {
public:
    int* candies;
    int candy(vector &ratings) {
        candies = new int[ratings.size()];
        for(int i = 0; i < ratings.size(); i++){
            candies[i] = 1;
        }
        
        for(int i = ratings.size() - 1; i > 0; i--){
            if(ratings[i] < ratings[i - 1]){
                candies[i - 1] = candies[i] + 1;
            }
        }
        
        for(int i = 0; i < ratings.size() - 1; i++){
            if(ratings[i] < ratings[i + 1]){
                int tmp = candies[i] + 1;
                if(candies[i + 1] < tmp){
                    candies[i + 1] = tmp;
                }
            }
        }
        
        int sum = 0;
        for(int i = 0; i < ratings.size(); i++){
            sum += candies[i];
        }
        
        return sum;
    }
};



你可能感兴趣的:(LeetCode,LeetCode题解)