There are n children standing in a line. Each child is assigned a rating value given in the integer array ratings.
You are giving candies to these children subjected to the following requirements:
Return the minimum number of candies you need to have to distribute the candies to the children.
Example 1:
Input: ratings = [4,3,5]
Output: 5Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
Example 2:
Input: ratings = [2,3,3]
Output: 4Explanation: 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.
Constraints:
1 <= ratings.length <= 20,0000 <= ratings[i] <= 20,000Before attempting this problem, you should be comfortable with:
We process children left to right, adjusting candies to satisfy the constraint that higher-rated children get more candy than their neighbors. When we increase a child's candy count, we may violate the constraint with a previous child, so we propagate updates backward as needed. This approach ensures correctness but may revisit the same positions multiple times.
class Solution:
def candy(self, ratings: List[int]) -> int:
n = len(ratings)
arr = [1] * n
for i in range(n - 1):
if ratings[i] == ratings[i + 1]:
continue
if ratings[i + 1] > ratings[i]:
arr[i + 1] = arr[i] + 1
elif arr[i] == arr[i + 1]:
arr[i + 1] = arr[i]
arr[i] += 1
for j in range(i - 1, -1, -1):
if ratings[j] > ratings[j + 1]:
if arr[j + 1] < arr[j]:
break
arr[j] += 1
return sum(arr)We can handle left and right neighbors separately. First, scan left to right to ensure each child with a higher rating than their left neighbor gets more candy. Then, scan right to left to handle the right neighbor constraint. When adjusting for right neighbors, we take the maximum of the current value and what the right constraint requires, preserving the left constraint satisfaction.
class Solution:
def candy(self, ratings: List[int]) -> int:
n = len(ratings)
arr = [1] * n
for i in range(1, n):
if ratings[i - 1] < ratings[i]:
arr[i] = arr[i - 1] + 1
for i in range(n - 2, -1, -1):
if ratings[i] > ratings[i + 1]:
arr[i] = max(arr[i], arr[i + 1] + 1)
return sum(arr)We can compute the result without storing candy counts for each child. The key insight is that ratings form a sequence of increasing and decreasing runs. For an increasing run of length k, we need 1+2+...+k extra candies above the base. For a decreasing run of length k, we also need 1+2+...+k extra candies. The peak between an increasing and decreasing run should belong to whichever run is longer.
n candies (one per child as the base).inc) to the result.class Solution:
def candy(self, ratings: List[int]) -> int:
n = len(ratings)
res = n
i = 1
while i < n:
if ratings[i] == ratings[i - 1]:
i += 1
continue
inc = 0
while i < n and ratings[i] > ratings[i - 1]:
inc += 1
res += inc
i += 1
dec = 0
while i < n and ratings[i] < ratings[i - 1]:
dec += 1
res += dec
i += 1
res -= min(inc, dec)
return resChildren with equal ratings do not need to have the same or related candy counts. Only strictly higher ratings require more candy than neighbors.
# Wrong: treating equal ratings like higher ratings
if ratings[i] >= ratings[i - 1]:
arr[i] = arr[i - 1] + 1A single left-to-right pass handles the left neighbor constraint but ignores the right neighbor. The two-pass approach ensures both constraints are satisfied.
In the right-to-left pass, simply setting arr[i] = arr[i + 1] + 1 may violate the left neighbor constraint already established. You must take the maximum of the current value and the right constraint.
# Wrong: overwrites left constraint
arr[i] = arr[i + 1] + 1
# Correct: preserves both constraints
arr[i] = max(arr[i], arr[i + 1] + 1)When counting increasing and decreasing sequences, the peak element gets counted in both. Forgetting to subtract min(inc, dec) results in overcounting candies.