InterviewPrepKit

Home / Coding / Binary Search

Search Suggestions System

medium Original ↗
Solving tips
  • Sort products first: all strings sharing a prefix then form one contiguous block, and the three suggestions are the first three entries of that block.
  • For each growing prefix, use bisect_left(products, prefix) to find the block start, then keep the next up-to-3 entries that actually startswith the prefix (the slice may overshoot past the block).
  • Optimization: each successive prefix's block can only move rightward, so resume bisect from the previous start index.
  • Complexity O(n log n * L) to sort plus O(m*(log n + L)) for the searches; a trie storing the 3 smallest words per node is the alternative when many queries share one build.

Problem

You are given a list of product names (products) and a string a user is typing (searchWord). After each character the user types, you must suggest at most three product names that start with the prefix typed so far. Suggestions must be the lexicographically smallest matches.

Return a list of lists: entry i holds the suggestions after the first i + 1 characters of searchWord have been typed. If fewer than three products match a prefix, return all matches; if none match, return an empty list for that prefix.

Examples

  • products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse"[["mobile","moneypot","monitor"],["mobile","moneypot","monitor"],["mouse","mousepad"],["mouse","mousepad"],["mouse","mousepad"]] After “m” and “mo” all five match, so we keep the three smallest; from “mou” onward only “mouse” and “mousepad” match.
  • products = ["havana"], searchWord = "havana"[["havana"],["havana"],["havana"],["havana"],["havana"],["havana"]] The single product matches every prefix of itself.
  • products = ["bags","baggage","banner","box","cloths"], searchWord = "bags"[["baggage","bags","banner"],["baggage","bags","banner"],["baggage","bags"],["bags"]] Note the suggestions are sorted, so “baggage” precedes “bags”.

Constraints

  • 1 <= len(products) <= 1000
  • 1 <= len(products[i]) <= 3000, total characters across products <= 2 * 10^4
  • 1 <= len(searchWord) <= 1000
  • All strings are lowercase English letters; product names are distinct.

Think about it first

Hint 1 If the products were sorted, where would all the strings sharing a given prefix sit relative to each other?
Hint 2 In a sorted list, every string with prefix `p` forms one contiguous block, and the three suggestions are the first three entries of that block. How do you find where the block starts without scanning?
Hint 3 Binary search (`bisect_left`) for the prefix itself: the insertion point is the first candidate. Check the next up-to-three entries and keep those that actually start with the prefix. Repeat for each successive prefix of `searchWord`, and note each search can resume from the previous insertion point.
Your workspace Not runnable by design — this is your interview scratchpad. Saved on this device.