/**
* 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?
*
* Tags: Greedy
*/
class Candy {
public static void main(String[] args) {
}
/**
* O(n) Time, O(n) Space
* From left to right, if ratings[i] increase, give one more
* From right to left, if ratings[i] increase, give one more
* Answer should be the max of two array
* Simplify second traversal by calculate and decide max right away
* And also calculate the sum
*/
public int candy(int[] ratings) {
int[] candies = new int[ratings.length];
candies[0] = 1;
for (int i = 1; i < ratings.length; i++)
candies[i] = ratings[i] > ratings[i - 1] ? candies[i - 1] + 1 : 1;
int res = candies[candies.length - 1];
for (int i = ratings.length - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1])
candies[i] = Math.max(candies[i], candies[i + 1] + 1);
res += candies[i];
}
return res;
}
/**
* O(n) Time, O(1) Space
* Use a var to store decreasing sequence length
* Use a var to store previous candies
*/
public int candyB(int[] ratings) {
if (ratings.length < 2) return ratings.length;
int res = 1;
int dec = 0;
int gap = 0;
int curCandy = 1;
for (int i = 1; i < ratings.length; i++) {
if (ratings[i] < ratings[i - 1]) {
if (dec == 0) gap = curCandy;
dec++;
curCandy = 1;
res += dec + curCandy;
if (gap > 1) {
gap--;
res--;
}
} else {
dec = 0;
if (ratings[i] > ratings[i - 1]) curCandy++;
else curCandy = 1;
res += curCandy;
}
}
return res;
}
}