Bird
Raised Fist0
Interview Prepgreedy-algorithmshardAmazonGoogleFacebook

Candy Distribution

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Steps
setup

Initialize candies array

Create a candies array with the same length as ratings, initializing all values to 1 because each child must have at least one candy.

💡 Starting with one candy per child ensures the minimum requirement before any increments.
Line:n = len(ratings) candies = [1] * n
💡 Every child starts with one candy, forming the baseline for further increments.
📊
Candy Distribution - Watch the Algorithm Execute, Step by Step
Watching each candy assignment and pointer movement reveals how the greedy approach ensures each child gets more candies than neighbors with lower ratings, which is hard to grasp from code alone.
Step 1/12
·Active fillAnswer cell
initialize
1
0
1
1
1
2
Result: 0
compare
1
0
i
1
1
1
2
Result: 0
compare
1
0
i
1
1
1
2
Result: 0
compare
1
0
1
1
i
1
2
Result: 0
compare
1
0
1
1
i
2
2
Result: 0
traverse
1
0
1
1
2
2
Result: 0
compare
1
0
i
1
1
2
2
Result: 0
compare
1
0
i
1
1
2
2
Result: 0
compare
i
1
0
1
1
2
2
Result: 0
compare
i
2
0
1
1
2
2
Result: 0
traverse
2
0
1
1
2
2
Result: 0
record
2
0
1
1
2
2
Result: 5

Key Takeaways

The two-pass greedy approach ensures candy distribution respects both left and right neighbor rating comparisons.

This insight is hard to see from code alone because the interplay of two passes and conditions is subtle without visualization.

Initializing all candies to 1 is crucial as a baseline before any increments.

It guarantees the minimum candy per child and simplifies the logic for increments.

The right-to-left pass corrects candy counts that the left-to-right pass alone cannot fix.

This step is essential to handle cases where a child has a higher rating than the right neighbor but was not assigned enough candies initially.

Practice

(1/5)
1. You are given a list of non-negative integers and need to arrange them to form the largest possible number when concatenated. Which algorithmic approach guarantees an optimal solution for this problem?
easy
A. Dynamic Programming to find the maximum concatenation by exploring all subsequences
B. Sorting the numbers as strings using a custom comparator that compares concatenations
C. Greedy approach by always picking the largest integer first
D. Brute force generating all permutations and selecting the maximum concatenation

Solution

  1. Step 1: Understand the problem requires ordering numbers to maximize concatenation

    The key is to compare pairs by concatenating in both possible orders and deciding which order yields a larger combined string.
  2. Step 2: Recognize that sorting with a custom comparator based on concatenation comparisons guarantees optimal order

    This approach ensures the final concatenation is lexicographically largest, unlike greedy or DP which do not handle pairwise ordering correctly.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Custom comparator sorting is the standard solution for this problem [OK]
Hint: Compare concatenations as strings to decide order [OK]
Common Mistakes:
  • Assuming greedy pick of largest integer works
  • Using DP which is unnecessary
  • Brute force is correct but inefficient
2. You are given a sequence of integers and need to find the length of the longest subsequence where the differences between successive elements strictly alternate between positive and negative. Which approach guarantees an optimal solution with O(n) time and O(1) space complexity?
easy
A. Dynamic Programming with a 2D table tracking subsequence lengths for each index and difference sign
B. Brute force recursion exploring all subsequences and checking alternating differences
C. Greedy approach tracking the direction of the last difference and counting peaks and valleys
D. Sliding window approach maintaining a contiguous alternating difference substring

Solution

  1. Step 1: Understand problem constraints

    The problem requires the longest subsequence with alternating positive and negative differences, not necessarily contiguous.
  2. Step 2: Identify optimal approach

    Dynamic programming is possible but less efficient; brute force is exponential; sliding window fails because subsequence need not be contiguous. The greedy approach tracking last difference direction and counting peaks and valleys achieves O(n) time and O(1) space optimally.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Greedy with direction tracking matches problem requirements [OK]
Hint: Longest alternating difference subsequence -> greedy direction tracking
Common Mistakes:
  • Confusing subsequence with substring
  • Assuming DP is always needed
  • Trying brute force without pruning
3. Consider the following buggy code for the Gas Station problem. Which line contains the subtle bug that can cause incorrect results?
def canCompleteCircuit(gas, cost):
    n = len(gas)
    net = [gas[i] - cost[i] for i in range(n)]
    # Bug: missing total gas check
    prefix = [0] * (2 * n + 1)
    for i in range(2 * n):
        prefix[i+1] = prefix[i] + net[i % n]
    for i in range(n):
        if prefix[i+n] - prefix[i] >= 0:
            return i
    return -1
medium
A. Line 3: net array computation
B. Line 4: missing total gas vs total cost check
C. Line 6: prefix sums computation loop
D. Line 8: checking prefix sums for valid start

Solution

  1. Step 1: Identify missing total gas check

    The code does not check if sum(net) < 0 before proceeding, which can cause incorrect start index or false positives.
  2. Step 2: Verify other lines

    Net array, prefix sums, and prefix difference checks are correct and standard.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Missing total gas check leads to incorrect results [OK]
Hint: Always check total gas >= total cost before searching start [OK]
Common Mistakes:
  • Forgetting total gas check
  • Misusing modulo in prefix sums
  • Resetting start without resetting tank
4. What is the worst-case time complexity of the BFS-based solution for Jump Game II on an input array of length n?
medium
A. O(n^2)
B. O(n)
C. O(n log n)
D. O(n^3)

Solution

  1. Step 1: Identify outer and inner loops

    The BFS processes each index once, but for each index, it may enqueue up to nums[pos] next positions, which can be up to n.
  2. Step 2: Analyze nested iteration

    In worst case (e.g., nums[i] = n for all i), inner loop runs O(n) times for each of O(n) indices -> O(n^2) total.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Nested loops over n indices and jumps -> O(n^2) [OK]
Hint: Nested loops over n indices and jumps -> O(n^2) [OK]
Common Mistakes:
  • Assuming BFS is always O(n)
  • Confusing with greedy linear time
  • Ignoring inner loop over jump range
5. What is the time complexity of the optimal greedy algorithm using a stack to remove k digits from a number string of length n to get the smallest number?
medium
A. O(n) because each digit is pushed and popped at most once
B. O(n^2) because nested loops are needed to find digits to remove
C. O(n log n) due to sorting digits internally
D. O(n * k) because each digit can cause up to k pops

Solution

  1. Step 1: Identify operations per digit

    Each digit is pushed onto the stack once and can be popped at most once when a smaller digit arrives.
  2. Step 2: Analyze total operations

    Since each push and pop happens at most once per digit, total operations are proportional to n.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Stack operations are linear in n, no nested loops [OK]
Hint: Each digit pushed/popped once -> O(n) time [OK]
Common Mistakes:
  • Assuming worst case k pops per digit -> O(n*k)
  • Confusing with sorting complexity
  • Thinking nested loops are needed