Lemonade Change
Keep two counters, fives and tens. A 5 adds a five. A 10 takes a five and adds a ten. For a 20, spend a 10 and a 5 whenever you can, and use three 5s only when there is no $10 to spend. If neither works, return false.
A 20 customer can be served only if the drawer holds a 10 and a 5, or three 5s. A 10 customer can be served only if the drawer holds a 5.
Problem
A lemonade costs 5. Customers line up one at a time, and each pays with a 5, 10 or 20 bill. You start with no money in the drawer.
Each customer must leave having paid exactly $5, so if they pay more, you must hand back the difference right away. Return true if you can give every customer the right change in order, and false if at some point you cannot.
An array bills, where bills[i] is the bill that customer i pays with. Every value is 5, 10 or 20.
true if every customer can get the right change, otherwise false.
The first three customers pay 5, so the drawer holds three 5 bills. The fourth pays 10 and gets a 5 back. The fifth pays 20 and gets a 10 and a $5 back.
After four customers the drawer holds two 10 bills and no 5 bill. The last customer needs 15 back, and two 10s cannot make that.
- β’ 1 β€ bills.length β€ 10^5
- β’ Each bill is 5, 10 or 20.
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck β each hint is counted.
- 1.
To give change to the next customer, what do you need to know about the drawer right now?
- 2.
A 5 bill can pay any change, but a 10 bill can only ever be handed out as part of a $20's change. Does that difference matter?
- 3.
For a 20 customer, how many different ways are there to hand back 15?
- 4.
If you had to choose one way for a $20, which one would leave you with the most options for later customers?
- 5.
Do you really need the full list of bills in the drawer, or is a count of each kind enough?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Recurse, trying 10 + 5 and 5 + 5 + 5 at each $20 bill | O(2^N) | O(N) |
| Optimal | Keep two counters; for a $20 use a $10 and a $5 when possible | O(N) | O(1) |
Why does this belong to this pattern?
- βchange for every customer, in orderβEach step depends on what is left in the drawer, so we walk the bills left to right and keep a running balance.
- βbills of $5, $10 and $20βOnly three bill types, so a count for each of the two change bills is enough. There is no need to store the drawer.
- βreturn true or falseβWe only need to know whether anyone gets stuck, so one failure is enough to stop.
This is a running balance question. The drawer must never run short, and it changes by one step per customer. What makes it different from a plain balance check is the choice for a $20: the two ways to make 15 leave different drawers. The greedy picks the one that keeps the most useful money, the 5s. In Candy and Gas Station there is no such choice to make.
Don't make this mistake
This looks like making change with as few small coins as possible, but the rule is about keeping the most useful money. With bills = [5, 5, 5, 5, 10, 20, 10], the wrong order pays the 20 with 5 + 5 + 5. That leaves no 5 and one 10, so the last 10 customer cannot get change and the answer is false. The right order pays 10 + 5 and keeps two $5s, so the answer is true.
Without tens++, the 10 disappears and a later 20 cannot use it. With bills = [5, 5, 10, 20], the right answer is true: the 10 takes a 5 back, and the 20 is paid as 10 + 5. The buggy version has no 10 for the 20, needs three 5s, has only one, and returns false.
If no $5 is in the drawer, the counter goes negative and later checks read nonsense. With bills = [10, 5, 5, 5, 5, 20], the first customer cannot get change, so the answer is false. Without the check, the counters are fives = β1, then fives = 3 at the $20, and the code returns true.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Greedy translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.