135: Candy
Hard


table of contents

The O(n) space complexity solution was quite straight-forward to come up with, taking a Greedy approach to solve this problem.

Basically, it hinges on the fact that if we make 2 passes (one from start to finish and another from finish to start), if the previous element’s rating is smaller than the current element’s rating, we can distribute 1 more candy to the current element than the previous element.

code

class Solution {
public:
    int candy(vector<int>& ratings) {
        vector<int> distributions(ratings.size(), 1);

        int ans = 0;
        for (int i = 1; i < ratings.size(); ++i) {
            if (ratings[i] > ratings[i-1]) {
                distributions[i] = distributions[i-1]+1;
            }
        }
        for (int i = ratings.size()-2; i >= 0; --i) {
            if (ratings[i] > ratings[i+1] && distributions[i] <= distributions[i+1]) {
                distributions[i] = distributions[i+1]+1;
            }
            ans += distributions[i+1];
        }
        ans += distributions[0];
        return ans;
    }
};

complexity

However, there does exist an O(1) solution (which only requires 1 pass).

The intuition for a solution like this is realise that for a rating distribution, like the one shown below, it also has the minimum candy distribution of:

As you can see from above, there are certain peaks. Reordering the peaks in a certain order can give us an intuition on how we can solve this problem in one pass:

(Maybe the example that I chose does not best represent the algorithm) Regardless, you might notice that the values in the array go through 3 states:

Code:

class Solution {
public:
    int candy(vector<int>& ratings) {
        vector<int> distributions(ratings.size(), 1);

        int ans = 1;
        int inc = 0, dec = 0, peak = 0;
        for (int i = 1; i < ratings.size(); ++i) {
            if (ratings[i] > ratings[i-1]) {
                ++inc;
                peak = inc;
                dec = 0;
                ans += inc+1;
            } else if (ratings[i] < ratings[i-1]) {
                ++dec;
                inc = 0;
                ans += dec+1 - int(peak >= dec);
            } else {
                inc = dec = peak = 0;
                ++ans;
            }
        }
        return ans;
    }
};

complexity