Distinct Subsequences
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
Count how many distinct subsequences of s equal t.
3Hint ladder
Take one rung at a time. Stop as soon as the idea clicks.
- Hint 1How many ways spell the empty prefix? Exactly one: use nothing.
- Hint 2Update the longer prefixes first within one source letter.
4The approach
Have you tried the hints? The approach is built as a path from the obvious way to the clever one.
How many ways can you pick letters from "rabbbit" (in order) to spell "rabbit"? Keep a counter for each prefix of the word: how many ways have I spelled "r", "ra", "rab", ... so far. When you meet a letter of the source, every prefix that ends with that letter gets extra ways equal to the ways of the prefix before it. Do the longer prefixes first, so one source letter is not used twice.
- The obvious way
Recursion choosing to use or skip each letter: O(2^n).
- The key insight
ways[k] = number of ways to form the first k letters of t from the part of s seen so far. ways[0] = 1. For each letter of s, for k from len(t) down to 1: if t[k - 1] equals this letter, ways[k] += ways[k - 1]. Answer ways[len(t)].
- The algorithm
- ways[0] = 1, others 0.
- For each source letter, go through the prefixes from longest to shortest.
- If the prefix ends with this letter, add the ways of the shorter prefix.
- Return ways[len(t)].
Watch it run
Examples = "rabbbit", t = "rabbit"
"r", "a" each extend the prefixes: "r" has 1 way, "ra" has 1 way.
ra: 1
Where people slip
- Loop the prefixes downwards; going upwards would reuse the same letter for two positions of t.
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 num_distinct(s, t):
ways = [1] + [0] * len(t) # ways[k]: spell the first k letters of t
for letter in s:
for taken in range(len(t), 0, -1): # longest prefix first: use each letter once
if t[taken - 1] == letter:
ways[taken] += ways[taken - 1]
return ways[len(t)]Now 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.