Top three suggestions as you type

Strings and tries Mid-level Python 3.13+ Reviewed By Best Latest Apps

Predict the output

What does this print?

Python 3.13
from bisect import bisect_left
words = sorted(["mouse", "mobile", "money", "monitor", "mousepad"])
i = bisect_left(words, "mou")
print(words[i:i + 3])

Options

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A ['mouse', 'mousepad']

Right: only two words start with 'mou'; a third slot holds nothing.

Slicing past the end of a list is safe in Python, but a real answer must also check each word starts with the prefix.

Why not the others?
  • B ['mouse', 'mousepad', 'money']. money sorts before mouse, so it is not after the search position.
  • C ['mobile', 'money', 'monitor']. Those come before 'mou' in sorted order.

30-second answer

Sort the words once. For each prefix, binary search the first word that is not smaller than the prefix; matching words follow it contiguously, so check the next three. Sorting costs O(n log n · L) and each prefix O(log n · L). For m typed letters the whole job is O((n + m) log n · L) time, with O(n) space for the sorted copy. A trie storing the top three at each node answers each prefix in O(1) after the build.

Practise saying it · 45 s. No recording, just a timer

Explain typing suggestions.

Say your answer out loud, then check which of these points you covered:

  • Sort once
  • Binary search each prefix
  • Take up to three matches

Deep dive

Sorted order puts all words sharing a prefix next to each other: the key fact.

Each new letter only narrows the range, so you can also move a lower bound forward without searching again.

Real autocomplete ranks by popularity; the structure is the same with a different sort key.

Python solution Ran on Python 3.13.5 · mypy --strict
Python 3.13
from bisect import bisect_left


def suggest(words: list[str], typed: str) -> list[list[str]]:
    ordered = sorted(words)
    out: list[list[str]] = []
    for end in range(1, len(typed) + 1):
        prefix = typed[:end]
        first = bisect_left(ordered, prefix)  # matches start here
        window = ordered[first:first + 3]
        picks = [w for w in window if w.startswith(prefix)]
        out.append(picks)
    return out

Common mistakes

  • Scanning all words for every prefix.
  • Returning words that merely contain the prefix.

Senior take & follow-ups

Say why sorting makes matches contiguous; the rest follows.

Follow-up questions

Think of your answer first, then open the hint.

  1. How would you rank by popularity?

    Show hint

    Store (score, word) at each trie node, keeping the top k by score.

  2. What changes with millions of users?

    Show hint

    Precompute top suggestions per prefix offline and serve them from a cache; see the Backend design page.

Similar on Backend: Design search autocomplete The Backend page designs an autocomplete service for many users; this page writes the lookup that returns suggestions for each typed prefix.

What each operation costs: Trie · KMP Algorithm · Rabin Karp · String Matching

From the author

DSA Master - Data & Algorithms

Free on iPhone and iPad: watch 50+ data structures and algorithms step through animations, run the code in the playground, and try the daily challenge.

Suggest a fix if something here is wrong or out of date.