Browse curriculum

Candy

Find the minimum number of candies to hand out so every child gets at least one and a child with a higher rating than a neighbor gets more, using two greedy passes.

Problem Understanding

Candy: n children stand in a line with ratings. Each child gets at least one candy, and a child with a higher rating than an adjacent child must get more candy than that neighbor. Return the minimum total.

Examples: [1,0,2] → 5 (2, 1, 2); [1,2,2] → 4 (1, 2, 1). Equal neighbors have no constraint between them.

The Intuition: One Rule per Direction

Split the condition into two independent rules and satisfy each with a greedy sweep:

  1. Left rule: a child rated above their left neighbor needs more than them. Sweeping left to right, set candies[i] = candies[i - 1] + 1 when it applies.
  2. Right rule: the mirror image, sweeping right to left.
  3. Both at once: in the second sweep take the max with what the first gave, so the left rule survives.

Two opposite sweeps that combine information from both sides are also the idea in Product of Array Except Self and Trapping Rain Water.

Interactive Walkthrough

HIGHER RATING THAN A NEIGHBOUR → MORE CANDY

ONE EACH

ratings

3
1
2
3
4
2

candies

1

0

1

1

1

2

1

3

1

4

1

5

pass

:

so far

6

total

:

 

Every child starts with 1 candy

Next

Rating 1 is not above 3 on the left: child 1 keeps 1

Free preview: the first 4 of 12 steps

ratings

Ratings are on top, candies below. The child being updated is filled, the neighbor it is compared with is marked, and a count the step raised is filled too. Watch the peak keep its 4 in the right pass.

Dry Run Table

Input: ratings = [3,1,2,3,4,2].

Pass candies
start [1,1,1,1,1,1]
left → right [1,1,2,3,4,1]
right → left [2,1,2,3,4,1]

In the right pass, child 4 (rating 4) needs only 2 against its right neighbor but keeps 4; child 0 (rating 3 > 1) rises to 2. Answer: 13.

The Solution Template

Two sweeps over one array.

Candy Code
1var candy = function(ratings) {
2 const n = ratings.length;
3 const candies = new Array(n).fill(1);
4 for (let i = 1; i < n; i++) {
5 if (ratings[i] > ratings[i - 1]) candies[i] = candies[i - 1] + 1;
6 }
7 for (let i = n - 2; i >= 0; i--) {
8 if (ratings[i] > ratings[i + 1]) candies[i] = Math.max(candies[i], candies[i + 1] + 1);
9 }
10 return candies.reduce((a, b) => a + b, 0);
11};

Edge Cases & Common Mistakes

  • Equal ratings: no rule applies, so neighbors may differ freely; [1,2,2] ends 1, 2, 1.
  • Overwriting in the second pass: use the max, or peaks lose candy.
  • One child: answer 1.
  • Strictly falling ratings: the left pass does nothing; the right pass does all the work.
  • One pass only: fails on any falling run, e.g. [2,1] needs 3, not 2.

Summary

Start everyone at 1. Sweep left to right giving one more than a lower-rated left neighbor, then right to left taking the max with one more than a lower-rated right neighbor, and sum. O(n) time and space.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Start at one

    Give every child 1 candy.

  2. Left pass

    Left to right: if ratings[i] > ratings[i - 1], set candies[i] = candies[i - 1] + 1.

  3. Right pass

    Right to left: if ratings[i] > ratings[i + 1], set candies[i] = max(candies[i], candies[i + 1] + 1); return the sum.

Frequently asked questions

Why are two passes needed?

Each child has two neighbors and two rules. The left-to-right pass satisfies every 'beat your left neighbor' rule, but only after seeing that neighbor; it cannot know about a long falling run to the right. The right-to-left pass handles the 'beat your right neighbor' rules the same way. Taking the max keeps both satisfied.


Why take the max in the second pass instead of overwriting?

At a peak, the left pass may already have given the child more than the right side needs, like 4 candies at the top of 1, 2, 3, 4. Overwriting with candies[i + 1] + 1 = 2 would break the rule against the left neighbor, who has 3.


Why is the result the minimum?

After the passes, each count equals the longer of the increasing run ending at it from the left and from the right. Any valid assignment needs at least that much: along an increasing run of length L each child needs one more than the previous, so the child at the end needs at least L. The greedy hits exactly that lower bound for every child.


Can it be done in O(1) space?

Yes, by counting the lengths of increasing and decreasing slopes in one pass and adding arithmetic sums, adjusting the peak to the larger slope. It is trickier to get right; the two-array version is the expected interview answer.

New to the technique behind this problem? Watch it run step by step:

Greedy Algorithms Visualization

Applying for software engineering roles? Free, no sign-up:

AI resume checker: match your resume to the job description