[leetcode] 135. Candy

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?

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.

我的解法

用pair來記錄等級以及他的下標,vector按等級排序,遍歷,判斷左右兩邊的等級

class Solution {
public:
    int candy(vector<int>& ratings) {
        int n = ratings.size();
        if(n==1)
            return 1;
        if(n==0)
            return 0;
        vector<pair<int,int>> v;
        for(int i=0;i<n;i++)
            v.push_back(make_pair(ratings[i],i));
        sort(v.begin(),v.end());
        
        int total=0;
        vector<int> can(n,0);
        for(int i=0;i<n;i++){
            int first = v[i].first;
            int second = v[i].second;
            if(second == 0)
                can[second] = first > ratings[second+1] ? can[second+1]+1 : 1;  
            else if(second == n-1)
                can[second] = first > ratings[second-1] ? can[second-1]+1 : 1;
            else if(first > ratings[second-1] && first > ratings[second+1] && second-1>=0 && second+1<n)
                can[second] = max(can[second-1], can[second+1]) +1;
            else if(first > ratings[second-1] && second-1>=0)
                can[second] = can[second-1]+1;
            else if(first > ratings[second+1] && second+1<n)
                can[second] = can[second+1]+1;
            else
                can[second] = 1;
            
            cout<<first<<" "<<second<<" "<<can[second]<<endl;
            total += can[second];
        }
        return total;
    }
    bool compare(const pair<int,int> &a, 
              const pair<int,int> &b){
        return a.second < b.second;
    }
};

解法1

首先初始化每個人一個糖果,然後這個算法需要遍歷兩遍,第一遍從左向右遍歷,如果右邊的小盆友的等級高,等加一個糖果,這樣保證了一個方向上高等級的糖果多。然後再從右向左遍歷一遍,如果相鄰兩個左邊的等級高,而左邊的糖果又少的話,則左邊糖果數爲右邊糖果數加一。最後再把所有小盆友的糖果數都加起來返回即可。

class Solution {
public:
    int candy(vector<int>& ratings) {
        int n = ratings.size();
        int total=0;
        vector<int> nums(n,1);
        for(int i=0;i<n-1;i++)
            if (ratings[i + 1] > ratings[i]) nums[i + 1] = nums[i] + 1;
        for(int i=n-1;i>0;i--)
            if (ratings[i -1] > ratings[i]) nums[i - 1] = max(nums[i] + 1, nums[i-1]);
        for(int i=0;i<n;i++)
            total += nums[i];
        return total;
    }
};

解法2

首先我們給第一個同學一個糖果,那麼對於接下來的一個同學就有三種情況:

  1. 接下來的同學的rating等於前一個同學,那麼給接下來的同學一個糖果就行。

  2. 接下來的同學的rating大於前一個同學,那麼給接下來的同學的糖果數要比前一個同學糖果數加1。

  3. 接下來的同學的rating小於前一個同學,那麼我們此時不知道應該給這個同學多少個糖果,需要看後面的情況。

對於第三種情況,我們不確定要給幾個,因爲要是隻給1個的話,那麼有可能接下來還有rating更小的同學,總不能一個都不給吧。也不能直接給前一個同學的糖果數減1,有可能給多了,因爲如果後面再沒人了的話,其實只要給一個就行了。還有就是,如果後面好幾個rating越來越小的同學,那麼前一個同學的糖果數可能還得追加,以保證最後面的同學至少能有1個糖果。來一個例子吧,四個同學,他們的rating如下:
1 3 2 1
先給第一個rating爲1的同學一個糖果,然後從第二個同學開始遍歷,第二個同學rating爲3,比1大,所以多給一個糖果,第二個同學得到兩個糖果。下面第三個同學,他的rating爲2,比前一個同學的rating小,如果我們此時給1個糖果的話,那麼rating更小的第四個同學就得不到糖果了,所以我們要給第四個同學1個糖果,而給第三個同學2個糖果,此時要給第二個同學追加1個糖果,使其能夠比第三個同學的糖果數多至少一個。那麼我們就需要統計出多有個連着的同學的rating變小,用變量cnt來記錄,找出了最後一個減小的同學,那麼就可以往前推,每往前一個加一個糖果,這就是個等差數列,我們可以直接利用求和公式算出這些rating減小的同學的糖果之和。然後我們還要看第一個開始減小的同學的前一個同學需不需要追加糖果,只要比較cnt和pre的大小,pre是之前同學得到的最大糖果數,二者做差加1就是需要追加的糖果數,加到結果res中即可

class Solution {
public:
    int candy(vector<int>& ratings) {
        if (ratings.empty()) return 0;
        int res = 1, pre = 1, cnt = 0;
        for (int i = 1; i < ratings.size(); ++i) {
            if (ratings[i] >= ratings[i - 1]) {
                if (cnt > 0) {
                    res += cnt * (cnt + 1) / 2;
                    if (cnt >= pre) res += cnt - pre + 1;
                    cnt = 0;
                    pre = 1;
                }
                pre = (ratings[i] == ratings[i - 1]) ? 1 : pre + 1;
                res += pre;
            } else {
                ++cnt;
            }
        }     
        if (cnt > 0) {
            res += cnt * (cnt + 1) / 2;
            if (cnt >= pre) res += cnt - pre + 1;
        }
        return res;
    }
};

參考

https://www.cnblogs.com/grandyang/p/4575026.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章