Combination Sum II
1Try it yourself first
Think for 20-30 minutes before you open any hint. Being stuck is where the learning happens.
Only for you, saved in this browser. After you see the approach you will compare it with your idea.2What is being asked
Numbers may repeat in the input; each number can be used only once. Return all unique combinations that add to the target.
3Hint ladder
Take one rung at a time. Stop as soon as the idea clicks.
- Hint 1Sort the numbers so equal ones are neighbours.
- Hint 2At one loop level, skip a number equal to the one just tried before it at that level.
4The approach
Have you tried the hints? The approach is built as a path from the obvious way to the clever one.
You hold a wallet of notes, some with the same value, and each note can be handed over once. If you have two ten-rupee notes, trying "first ten" and then "second ten" as the first note gives identical payments. So at each decision point, once you have tried one ten, skip the other ten as the starter. But you may still use both tens in one payment, one after the other.
- The obvious way
Generate all subsets, keep those that sum to target, de-duplicate with a set.
- The key insight
Sort. Recurse with (start, remaining). In the loop: skip a number if it equals the previous number AND it is not the first of this loop (this level already tried that value). Stop if the number is bigger than remaining. Choose it, recurse from the NEXT position (single use), un-choose.
- The algorithm
- Sort the numbers.
- remaining == 0: save a copy.
- In the loop skip repeats of a value already tried at this level; stop when too big.
- Choose, recurse from the next position, un-choose.
Watch it run
Examplecandidates = [10,1,2,7,6,1,5], target = 8 (sorted: 1 1 2 5 6 7 10)
Start with the first 1. With the second 1 and then 6 we get 1 + 1 + 6 = 8. Record [1,1,6].
found: [1,1,6]
Where people slip
- The skip test is position > start, not position > 0; otherwise you also block legal repeats used in one payment.
How close was your idea?
You did not write an idea, and that is fine.
Be honest with yourself. This sets your revision list.
5Code
Try writing it yourself from the steps first. Then compare.
def combination_sum2(candidates, target):
candidates.sort()
result = []
chosen = []
def pay(start, remaining):
if remaining == 0:
result.append(list(chosen))
return
for position in range(start, len(candidates)):
if position > start and candidates[position] == candidates[position - 1]:
continue # this level already tried this value
note = candidates[position]
if note > remaining:
break
chosen.append(note)
pay(position + 1, remaining - note) # each note is handed over only once
chosen.pop()
pay(0, target)
return resultNow close this and write it again from memory, in the language you will use in the interview. Reattempt after 1 day, 7 days and about 30 days.
6Still stuck? Watch a video
Seeing someone explain it out loud can make it click. Try the video after you have read the approach above.