The Celebrity Problem
Suppose you are at a party with n people labeled 0 to n-1. Among them, there may exist one celebrity: everyone knows the celebrity, but the celebrity knows no one. Given a helper function knows(a, b) that returns true if person a knows person b, find the celebrity or return -1 if none exists. Minimize the number of API calls.
- 2 <= n <= 1000
- knows(a, b) counts as one API call
- There is at most one celebrity
n=3, knows: 0 knows 1, 2 knows 11n=2, nobody knows each other-1n=3, everyone knows everyone-1The brute force asks, for every pair, "does A know B?" — up to N² questions. The way out is one sharp observation: a single question knows(A, B) always eliminates exactly one person, no matter the answer.
- If A knows B → A can't be the celebrity (a celebrity knows no one). A is out.
- If A doesn't know B → B can't be the celebrity (everyone knows the celebrity). B is out.
Either way, one suspect is gone for good. So keep a pool of suspects, repeatedly take two, ask one question, drop the loser, and put the survivor back. After N−1 questions exactly one candidate remains.
A stack (a pile you push onto and pop from the top, last-in-first-out) is a convenient container for that pool — pop two, push the survivor back — but be honest about what's happening: the stack here is just a bag of remaining candidates. It isn't doing anything stack-specific; a plain index sweeping the array once shrinks the pool the same way, with no stack at all. The transferable idea in this problem isn't the data structure; it's the elimination: when one comparison can rule out one of two options, you can shrink N candidates to 1 in N−1 steps instead of checking every pair.
One catch: elimination only produces a candidate. It guarantees that if a celebrity exists, it must be this person — it does not guarantee one exists at all. So a second pass verifies: does the candidate know no one, and does everyone else know them? If not, return -1.
def find_celebrity(n):
# Phase 1 — elimination: each question drops exactly one suspect
stack = list(range(n))
while len(stack) > 1:
a = stack.pop()
b = stack.pop()
if knows(a, b):
stack.append(b) # a knows someone -> a is out
else:
stack.append(a) # a doesn't know b -> b is out
cand = stack.pop()
# Phase 2 — verify the survivor really is a celebrity
for i in range(n):
if i == cand:
continue
if knows(cand, i) or not knows(i, cand):
return -1
return candknows(2, 1)? Yes → 2 is out, push 1 → [0, 1]knows(1, 0)? No → 0 is out, push 1 → [1]Recognize the elimination trick anywhere a relation lets one comparison discard one of two items — whether you stash the pool in a stack, a queue, or a single pointer barely matters.
The Celebrity Problem Strategy
Mental Model
If A knows B, A cannot be the celebrity.
If A don't know B, B cannot be the celebrity.
O(N) Complexity
Instead of an O(N²) matrix scan, the elimination tournament strategy finds the truth in linear time by removing one person from contention in every comparison!