Lemonade Change
This question is asked by Amazon. You're running a popsicle stand where each popsicle costs $5. Each customer you encountered pays with either a $5 bill, a $10 bill, or a $20 bill and only buys a single popsicle. The customers that come to your stand come in the ordered given by the customers array where customers[i] represents the bill the ith customer pays with. Starting with $0, return whether or not you can serve all the given customers while also giving the correct amount of change.
Example(s)
Example 1:
Input: customers = [5, 10]
Output: true
Explanation:
Customer 1: Pays $5, no change needed
Cash: $5 bills = 1, $10 bills = 0
Customer 2: Pays $10, needs $5 change
Give $5 change, cash: $5 bills = 0, $10 bills = 1
Can serve all customers.
Example 2:
Input: customers = [10]
Output: false
Explanation:
Customer 1: Pays $10, needs $5 change
But we have $0, cannot give change
Cannot serve customer.
Example 3:
Input: customers = [5, 5, 5, 10, 20]
Output: true
Explanation:
Customer 1: Pays $5, no change needed
Cash: $5 = 1, $10 = 0
Customer 2: Pays $5, no change needed
Cash: $5 = 2, $10 = 0
Customer 3: Pays $5, no change needed
Cash: $5 = 3, $10 = 0
Customer 4: Pays $10, needs $5 change
Give $5 change, cash: $5 = 2, $10 = 1
Customer 5: Pays $20, needs $15 change
Give $10 + $5 change, cash: $5 = 1, $10 = 0
Can serve all customers.
Example 4:
Input: customers = [5, 5, 10, 10, 20]
Output: false
Explanation:
Customer 1: Pays $5, cash: $5 = 1
Customer 2: Pays $5, cash: $5 = 2
Customer 3: Pays $10, give $5 change, cash: $5 = 1, $10 = 1
Customer 4: Pays $10, give $5 change, cash: $5 = 0, $10 = 2
Customer 5: Pays $20, needs $15 change
Need $10 + $5 or 3 × $5, but we have $5 = 0
Cannot give change.
Solution
The solution uses Greedy Algorithm:
- Track cash: Keep count of $5 and $10 bills we have
- Process customers: For each customer payment:
- $5: Take it, no change needed
- $10: Give $5 change (need one $5 bill)
- $20: Give $15 change (prefer $10 + $5, else 3 × $5)
- Check feasibility: Return false if we can't give change
- JavaScript Solution
- Python Solution
JavaScript Solution - Greedy
/**
* Check if we can serve all customers with correct change
* @param {number[]} customers - Array of customer payments (5, 10, or 20)
* @return {boolean} - Whether we can serve all customers
*/
function lemonadeChange(customers) {
let five = 0; // Count of $5 bills
let ten = 0; // Count of $10 bills
for (const bill of customers) {
if (bill === 5) {
// Customer pays $5, no change needed
five++;
} else if (bill === 10) {
// Customer pays $10, need to give $5 change
if (five === 0) {
return false; // Cannot give change
}
five--;
ten++;
} else if (bill === 20) {
// Customer pays $20, need to give $15 change
// Prefer giving $10 + $5 (greedy: preserve $5 bills)
if (ten > 0 && five > 0) {
ten--;
five--;
} else if (five >= 3) {
// Give 3 × $5 if we don't have $10 + $5
five -= 3;
} else {
return false; // Cannot give change
}
}
}
return true; // Served all customers
}
// Test cases
console.log('Example 1:', lemonadeChange([5, 10]));
// true
console.log('Example 2:', lemonadeChange([10]));
// false
console.log('Example 3:', lemonadeChange([5, 5, 5, 10, 20]));
// true
console.log('Example 4:', lemonadeChange([5, 5, 10, 10, 20]));
// falseOutput:
Python Solution - Greedy
from typing import List
def lemonade_change(customers: List[int]) -> bool:
"""
Check if we can serve all customers with correct change
Args:
customers: Array of customer payments (5, 10, or 20)
Returns:
bool: Whether we can serve all customers
"""
five = 0 # Count of $5 bills
ten = 0 # Count of $10 bills
for bill in customers:
if bill == 5:
# Customer pays $5, no change needed
five += 1
elif bill == 10:
# Customer pays $10, need to give $5 change
if five == 0:
return False # Cannot give change
five -= 1
ten += 1
elif bill == 20:
# Customer pays $20, need to give $15 change
# Prefer giving $10 + $5 (greedy: preserve $5 bills)
if ten > 0 and five > 0:
ten -= 1
five -= 1
elif five >= 3:
# Give 3 × $5 if we don't have $10 + $5
five -= 3
else:
return False # Cannot give change
return True # Served all customers
# Test cases
print('Example 1:', lemonade_change([5, 10]))
# True
print('Example 2:', lemonade_change([10]))
# False
print('Example 3:', lemonade_change([5, 5, 5, 10, 20]))
# True
print('Example 4:', lemonade_change([5, 5, 10, 10, 20]))
# FalseOutput:
Complexity
- Time Complexity: O(n) - Where n is the number of customers. We iterate through the customers array once.
- Space Complexity: O(1) - Only using a constant amount of extra space to track $5 and $10 bills.
Approach
The solution uses Greedy Algorithm:
-
Track cash:
- Keep count of $5 bills and $10 bills we have
- We don't need to track $20 bills (we give them as change, but never use them)
-
Process each customer:
- $5 payment: Take it, increment $5 count (no change needed)
- $10 payment: Need to give $5 change
- If we have a $5 bill, give it and increment $10 count
- Otherwise, return false
- $20 payment: Need to give $15 change
- Prefer: Give one $10 and one $5 (greedy: preserves $5 bills for future $10 customers)
- Else: Give three $5 bills
- Otherwise, return false
-
Greedy choice:
- When giving change for $20, prefer $10 + $5 over 3 × $5
- This preserves $5 bills which are more useful for $10 customers
Key Insights
- Greedy algorithm: Prefer giving $10 + $5 for $20 payments
- Track only $5 and $10: $20 bills are received but not used for change
- Preserve $5 bills: They're needed for $10 customers
- O(n) time: Single pass through customers
- O(1) space: Only track two counts
Step-by-Step Example
Let's trace through Example 3: customers = [5, 5, 5, 10, 20]
customers = [5, 5, 5, 10, 20]
five = 0, ten = 0
Customer 1: Pays $5
five = 1, ten = 0
No change needed
Customer 2: Pays $5
five = 2, ten = 0
No change needed
Customer 3: Pays $5
five = 3, ten = 0
No change needed
Customer 4: Pays $10, needs $5 change
Check: five > 0? Yes (five = 3)
Give $5 change: five = 2, ten = 1
Customer 5: Pays $20, needs $15 change
Option 1: ten > 0 and five > 0? Yes (ten = 1, five = 2)
Give $10 + $5: ten = 0, five = 1
Success!
Result: true (served all customers)
Let's trace through Example 4: customers = [5, 5, 10, 10, 20]
customers = [5, 5, 10, 10, 20]
five = 0, ten = 0
Customer 1: Pays $5
five = 1, ten = 0
Customer 2: Pays $5
five = 2, ten = 0
Customer 3: Pays $10, needs $5 change
Check: five > 0? Yes (five = 2)
Give $5 change: five = 1, ten = 1
Customer 4: Pays $10, needs $5 change
Check: five > 0? Yes (five = 1)
Give $5 change: five = 0, ten = 2
Customer 5: Pays $20, needs $15 change
Option 1: ten > 0 and five > 0? No (ten = 2, five = 0)
Option 2: five >= 3? No (five = 0)
Cannot give change!
Result: false (cannot serve customer 5)
Visual Representation
Example 3: customers = [5, 5, 5, 10, 20]
Cash state after each customer:
Start: $5 = 0, $10 = 0
After $5: $5 = 1, $10 = 0
After $5: $5 = 2, $10 = 0
After $5: $5 = 3, $10 = 0
After $10: $5 = 2, $10 = 1 (gave $5 change)
After $20: $5 = 1, $10 = 0 (gave $10 + $5 change)
Result: true ✓
Example 4: customers = [5, 5, 10, 10, 20]
Cash state after each customer:
Start: $5 = 0, $10 = 0
After $5: $5 = 1, $10 = 0
After $5: $5 = 2, $10 = 0
After $10: $5 = 1, $10 = 1 (gave $5 change)
After $10: $5 = 0, $10 = 2 (gave $5 change)
After $20: Need $15 change
Need: $10 + $5 or 3 × $5
Have: $10 = 2, $5 = 0
Cannot give change! ✗
Result: false
Edge Cases
- Empty array: Return true (no customers to serve)
- All $5: Return true (no change needed)
- All $10: Return false (need $5 for change, but start with $0)
- All $20: Return false (need $15 change, but start with $0)
- First customer $10 or $20: Return false (no change available)
Important Notes
- Greedy choice: Prefer $10 + $5 for $20 payments
- Track $5 and $10: $20 bills received but not used for change
- Preserve $5 bills: More useful for $10 customers
- O(n) time: Single pass through customers
- O(1) space: Only track two counts
Why Greedy Works
Key insight:
- When giving change for $20, we have two options:
- Give $10 + $5 (uses one $10 and one $5)
- Give 3 × $5 (uses three $5)
- We should prefer $10 + $5 because:
- $5 bills are more valuable (needed for $10 customers)
- Using a $10 bill when possible preserves $5 bills
- This greedy choice is optimal
Proof sketch:
- If we can serve customers with greedy, we can serve them with any strategy
- If we cannot serve with greedy, we cannot serve with any strategy
- The greedy choice (prefer $10 + $5) maximizes future flexibility
Related Problems
- Coin Change: Similar change-making problem
- Assign Cookies: Different greedy problem
- Queue Reconstruction by Height: Different greedy problem
- Non-overlapping Intervals: Different greedy problem
Takeaways
- Greedy algorithm solves this efficiently
- Prefer $10 + $5 for $20 payments (preserves $5 bills)
- Track only $5 and $10 bills
- O(n) time single pass through customers
- O(1) space only track two counts
- Classic greedy problem with practical applications