Tuesday, December 31, 2013

Day 70, ##, 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?
---------------------------------------------------------
Solution #1, O(n) space and complexity
scan ratings twice, from beginning to end then backwards
class Solution {
public:
    int candy(vector<int> &ratings) {
        int n = ratings.size();
        vector<int> candy(n,1);
        for (int i = 1; i < n; i++) {
            if (ratings[i] > ratings[i - 1]) {
                candy[i] = candy[i - 1] + 1;
            }
        }
        
        int sum = candy[n - 1];
        for (int i = n -2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1] && candy[i] <= candy[i + 1]) {
                candy[i] = candy[i + 1] + 1;
            }
            sum += candy[i];
        }
        return sum;
    }
};
Solution#2, O(1) space, but hard to get all corner cases right
Update on Dec-24-2014 
constant space
Constant space, O(n) complexity
#1 When index reaches 1 or 2, all candies at indexes before 1 or 2 can be finalized. So update totalCandy, clear curSum, reset current candy given at current index, top index and topCandy
#2 When ratings[i] < ratings[i - 1], increment all candies between current index and top(both should be exclusive) by one, and add 1 candy for current index. Then check if candies at [top], which is topCandy, is equal to i - top. if it is the case, increment topCandy and curSum.
for example, index_1 has 3 candies, index_3 has 3, index_4 has 2, we have to give one more candy to index_1


class Solution {
public:
    int candy(vector<int> &ratings) {
        int top = 0;
        int totalCandy = 0;
        int curSum = 1;
        int candy = 1;
        int topCandy = 1;
        
        for (int i= 1; i < ratings.size(); i++) {
            if (ratings[i] < ratings[i - 1]) {
                curSum += i - top - 1 + 1; // for clarity
                if (topCandy == i - top) {
                    curSum++;
                    topCandy++;
                }
                candy = 1;
            }else if (ratings[i] == ratings[i - 1]) {
                candy = 1;
                top = i;
                totalCandy += curSum;
                curSum = 1;
                topCandy = 1;
            }else {
                top = i;
                candy++;
                totalCandy += curSum;
                curSum = candy;
                topCandy = candy;
            }
        }
        
        return totalCandy + curSum;
    }
};

No comments:

Post a Comment