Problem link:
http://oj.leetcode.com/problems/candy/
Suppose we are given an array R[1..N] that are ratings of N children.
Let C[1..N] be a new array where C[i] is the number of candies for i-th child.
From the description, C[i] should meet following requirements:
LEAST. C[i] is at least 1, for i = 1, ..., N
LEFT. C[i] > C[i-1] if R[i] > R[i-1], for i = 2, ..., N
RIGHT. C[i] > C[i+1] if R[i] > R[i+1], for i = 1, ..., N-1
Each C[i] should satisfy these three requirements, excpet that C[1] only needs to meet LEAST and RIGHT and C[N] only needs to meet LEAST and LEFT.
To get the minimum number of candies, we desgin the following algorithm:
- Initialize the array C[1..N] with value of 1
- Scan the array R from left to right, and update C[] to meet LEFT. That is, for each i = 2 to N,
- if R[i] > R[i-1], then C[i] = C[i+1]
- else, keep C[i] = 1
- Now, C[] satisfies LEAST and LEFT. Then scan the array R from right to left, update C[] not only meeting RIGHT but also keeping LEFT satisfied. That is, for each i = N-1 to 1,
- if R[i] > R[i+1], then C[i] = max(C[i], C[i+1]+1)
- else, keep C[i] unchanged
The algorithm computes C[] satisfying LEAST, LEFT, and RIGHT requirements. Since each time we increment C[i] by 1 to meet LEFT or RIGHT, so the total sum of C[] should be minimum (not sure how to prove the correctness, maybe a contradiction method needed). The algorithm can be finished in O(n) time. And the following code is the python solution accepted by oj.leetcode.com.
class Solution: # @param ratings, a list of integer # @return an integer def candy(self, ratings): # Specail cases n = len(ratings) if n < 2: return n # First scan, from left to right # only consider the following LEFT conditions: # if one's rating is higher than his left neighbor, # then he should have more candies than his left neighbor c = [0] * n c[0] = 1 for p in xrange(1,n): if ratings[p] > ratings[p-1]: c[p] = c[p-1] + 1 else: c[p] = 1 # Second scan, from right to left # consider both RIGHT and LEFT conditions: # if c[p]'s rating is higher than his right neighbor, # then c[p] = max(c[p], c[p+1]+1), otherwise keep c[p] unchagned for p in xrange(n-2, -1, -1): if ratings[p] > ratings[p+1]: c[p] = max(c[p], c[p+1]+1) # Return the sum return sum(c)