Assign Cookies
Child i is content if they get a cookie of size at least their greed g[i]. Each child gets at most one cookie. Maximize the number of content children.
Intuition
Sort both lists and hand the smallest useful cookie to the least greedy child. A big cookie spent on an easily-pleased kid is a waste — matching small with small keeps the large cookies for the kids who actually need them.
Two sorted lists walked with two pointers — the exchange-argument greedy. Give the smallest adequate cookie to the least demanding child: any other assignment can be swapped for this one without losing a match, so greedy is provably optimal. That swap argument is the standard way to prove a greedy is safe.
Approach
Why greedy is safe here
Suppose an optimal solution gives the least greedy unfed child a bigger cookie than necessary. Swap it with the smallest cookie that satisfies them — nothing breaks, and the bigger cookie is freed for someone greedier. Repeating this argument turns any optimal solution into the greedy one, so greedy is optimal.
Two pointers over two sorted lists
Sort g (greed) and s (cookies). Walk the cookies smallest-first with a pointer child into the greed list: if the current cookie satisfies g[child], feed them and advance child; otherwise the cookie is too small for everyone remaining (they're sorted!) — discard it and try the next.
The child pointer is the answer
Every advance of child is one content kid, and no cookie is ever reconsidered. One pass after sorting: O(n log n + m log m) time, O(1) extra space. child ends as the count.
Solution & live demo
Common pitfalls
Assigning the largest cookies first
g.sort(reverse=True) s.sort(reverse=True)
g.sort() s.sort()
Spending a big cookie on a child a small one would satisfy wastes capacity that a greedier child may need. Ascending order guarantees each cookie goes to the least demanding child it can still satisfy.
Advancing the child pointer on a failed match
for cookie in s:
if g[child] <= cookie: child += 1
else: child += 1if child < len(g) and g[child] <= cookie:
child += 1A child that this cookie can't satisfy should stay in line for a bigger one, not be skipped. Only a successful assignment advances the child.
Indexing past the end of the children list
if g[child] <= cookie:
if child < len(g) and g[child] <= cookie:
With more cookies than children the loop keeps running after every child is served, and g[child] goes out of range. The bound check has to come first.
Edge cases
The loop body never feeds anyone — return 0.
Every comparison fails; child never advances; answer 0.
Once child == len(g) everyone is fed — break early; extra cookies are irrelevant.