Bird
Raised Fist0
Interview PreptriesmediumAmazonGoogleFacebook

Search Suggestions System (Autocomplete)

Choose your preparation mode4 modes available
▶
Steps
setup

Initialize root node and sort products

Create the root TrieNode with empty children and suggestions. Sort the products lexicographically to ensure suggestions are stored in order.

💡 Sorting products first guarantees that suggestions stored at nodes are always the lexicographically smallest.
Line:root = TrieNode() products.sort()
💡 Sorting before insertion simplifies maintaining top 3 suggestions at each node.
📊
Search Suggestions System (Autocomplete) - Watch the Algorithm Execute, Step by Step
Watching the trie construction and prefix traversal step-by-step reveals how the algorithm efficiently narrows down suggestions without scanning all products repeatedly.
Step 1/16
·Active fill★Answer cell
insert
insert
mobile
m
insert
mobile
mo
insert
mobile
mob
insert
mobile
mobi
insert
mobile
mobil
insert
mobile
mobile*
insert
moneypot
mo
insert
moneypot
mo
insert
moneypot
mon
search
mouse
m
Search: true
search
mouse
mo
Search: true
search
mouse
mou
Search: true
search
mouse
mous
Search: true
search
mouse
mouse*
Search: true
search
mouse*
Search: true

Key Takeaways

✓ Sorting products before insertion ensures suggestions at each node are lexicographically smallest.

Without sorting, maintaining top 3 lex order suggestions at nodes would be more complex.

✓ Trie nodes store up to three suggestions, enabling efficient prefix-based autocomplete without scanning all products.

This reduces search time drastically compared to naive scanning for each prefix.

✓ Traversing the trie for each prefix of the searchWord collects suggestions incrementally, demonstrating the power of prefix trees.

Seeing the active path and suggestions at each step clarifies how autocomplete narrows down options.

Practice

(1/5)
1. What is the time complexity of the optimal trie + BFS approach for finding the longest word in a dictionary with n words, each of average length m?
medium
A. O(n * m + n * 26) because building trie takes O(n*m) and BFS visits each node once
B. O(n * m * 26) since BFS explores all children for each character
C. O(n * m^2) due to checking all prefixes for each word
D. O(n * m log n) due to sorting children at each node during BFS

Solution

  1. Step 1: Analyze trie construction

    Inserting n words of length m takes O(n * m) time as each character is processed once.
  2. Step 2: Analyze BFS traversal

    BFS visits each node once; each node has up to 26 children, so total BFS cost is O(n * 26) which is O(n).
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Trie build + BFS traversal sum to O(n*m + n*26) [OK]
Hint: Trie build O(n*m), BFS O(n*26) combined [OK]
Common Mistakes:
  • Confusing BFS cost as O(n*m*26)
  • Forgetting BFS visits each node once
  • Assuming sorting children adds log factor per node
2. What is the time complexity of the optimal Trie + DFS backtracking approach for finding palindrome pairs in a list of n words, each of maximum length k?
medium
A. O(n * k)
B. O(n^2 * k)
C. O(n * k * log n)
D. O(n * k^2)

Solution

  1. Step 1: Identify outer and inner loops

    There are n words, each of length k. Trie insertion and search involve iterating over k characters.
  2. Step 2: Analyze palindrome checks and DFS

    Palindrome checks on suffixes/prefixes cost O(k) each, done during insertion and search, leading to O(k^2) per word.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Trie + palindrome checks cause quadratic factor in k, linear in n [OK]
Hint: Palindrome checks inside loops cause k^2 factor [OK]
Common Mistakes:
  • Assuming brute force O(n^2 * k)
  • Ignoring palindrome check cost
  • Confusing log n factor
3. The following code attempts to implement the optimal StreamChecker. Identify the single line that contains a subtle bug that can cause incorrect results or inefficiency.
class StreamChecker:
    def __init__(self, words):
        self.root = TrieNode()
        self.max_len = max(len(w) for w in words)
        self.stream = []
        for word in words:
            node = self.root
            for ch in word:  # Bug here: words not reversed
                if ch not in node.children:
                    node.children[ch] = TrieNode()
                node = node.children[ch]
            node.is_word = True

    def query(self, letter):
        self.stream.append(letter)
        if len(self.stream) > self.max_len:
            self.stream.pop(0)
        node = self.root
        for ch in reversed(self.stream):
            if ch not in node.children:
                return False
            node = node.children[ch]
            if node.is_word:
                return True
        return False
medium
A. Line: for ch in word:
B. Line: if len(self.stream) > self.max_len:
C. Line: for ch in reversed(self.stream):
D. Line: if node.is_word:

Solution

  1. Step 1: Identify how trie is built

    The code inserts words in forward order instead of reversed order, which breaks suffix matching logic.
  2. Step 2: Understand impact on query

    Query traverses reversed stream, expecting reversed trie. Since trie is built forward, traversal fails to find matches.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Reversing words during trie build is essential for suffix queries [OK]
Hint: Trie must be built with reversed words for suffix matching [OK]
Common Mistakes:
  • Not reversing words when building trie
  • Not limiting stream buffer
  • Returning false too early
4. Examine the following buggy code snippet for the Word Break problem using iterative DP and a reversed trie. Which line contains the subtle bug that can cause incorrect results on some inputs?
medium
A. Line initializing dp array without setting dp[0] = True
B. Line inserting reversed words into the trie
C. Line breaking inner loop when character not found in children
D. Line checking if node.is_word and dp[j] before setting dp[i]

Solution

  1. Step 1: Identify base case initialization

    dp[0] must be True to represent empty string segmentation. Missing this causes dp[i] never to become True.
  2. Step 2: Confirm other lines are correct

    Trie insertion, loop breaks, and condition checks are correct and necessary for correctness and efficiency.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    dp[0] = True is essential base case [OK]
Hint: dp[0] must be True to start segmentation [OK]
Common Mistakes:
  • Forgetting dp[0] = True
  • Not breaking early in inner loop
  • Incorrect trie insertion order
5. Examine the following buggy snippet from the Trie + DFS solution. Which line contains the subtle bug that can cause incorrect results or infinite loops?
def dfs(r, c, node):
    if r < 0 or r >= rows or c < 0 or c >= cols:
        return
    char = board[r][c]
    if char == '#' or char not in node.children:
        return
    node = node.children[char]
    if node.word:
        result.append(node.word)
        node.word = None
    # BUG: Missing marking visited cell
    dfs(r+1, c, node)
    dfs(r-1, c, node)
    dfs(r, c+1, node)
    dfs(r, c-1, node)
    # BUG: Missing restoring cell after DFS
medium
A. Line checking if char == '#' or char not in node.children
B. Lines calling dfs recursively without marking visited cells
C. Line appending node.word to result and setting node.word = None
D. Line updating node = node.children[char]

Solution

  1. Step 1: Identify missing visited cell marking

    The code does not mark the current cell as visited before recursive calls, allowing revisits and potential infinite loops.
  2. Step 2: Identify missing restoring cell state

    Without restoring the cell after DFS, subsequent searches see corrupted board state, causing incorrect results.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Missing visited marking causes infinite loops or incorrect word detection [OK]
Hint: Always mark and restore visited cells in DFS [OK]
Common Mistakes:
  • Forgetting to mark visited cells
  • Not restoring board state after DFS
  • Appending duplicates without clearing node.word
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard