Bird
Raised Fist0
Interview PreptriesmediumAmazonGoogleFacebook

Replace Words (Word Root Dictionary)

Choose your preparation mode4 modes available
▶
Steps
setup

Initialize Trie Root

Create the root node of the trie, which is empty and has no children yet.

💡 The root node is the starting point for all insertions and searches in the trie.
Line:class Trie: def __init__(self): self.root = TrieNode()
💡 The trie starts empty with a single root node.
📊
Replace Words (Word Root Dictionary) - Watch the Algorithm Execute, Step by Step
Watching the trie construction and prefix search step-by-step reveals how the algorithm efficiently replaces words by their roots without scanning the entire dictionary for each word.
Step 1/21
·Active fill★Answer cell
insert
insert
cat
c
insert
cat
ca
insert
cat
at*
insert
bat
b
insert
bat
ba
insert
bat
at*
insert
rat
r
insert
rat
ra
insert
rat
at*
search
search
the
Search: false
search
cattle
c
search
cattle
ca
search
cattle
at*
Search: true
search
rattled
r
search
rattled
ra
search
rattled
at*
Search: true
search
battery
b
search
battery
at*
Search: true
reconstruct

Key Takeaways

✓ Building a trie from dictionary roots allows efficient prefix searches for replacement.

This is hard to see from code alone because the trie structure and its incremental growth are abstract without visualization.

✓ The search stops as soon as an end_of_word node is found, ensuring the shortest root prefix is used.

Understanding early stopping in the trie traversal clarifies why the shortest prefix is chosen.

✓ Words without any matching root prefix remain unchanged, preserving sentence meaning.

Seeing the failed search path visually helps understand why some words are not replaced.

Practice

(1/5)
1. You need to design a data structure that supports inserting key-value pairs and efficiently returning the sum of all values of keys that start with a given prefix. Which approach guarantees the most optimal time complexity for both insert and sum operations?
easy
A. Use a hash map to store all keys and values, and scan all keys on each sum query to accumulate matching prefixes.
B. Use a dynamic programming approach to precompute sums for all possible prefixes and update them on each insert.
C. Use a balanced binary search tree keyed by strings, and perform range queries for prefix sums.
D. Use a trie where each node stores the cumulative sum of all keys passing through it, updating sums on insert and traversing prefix nodes on sum queries.

Solution

  1. Step 1: Understand the problem requirements

    The data structure must support fast insertions and prefix sum queries.
  2. Step 2: Evaluate approaches

    Hash map with scanning is O(n*k) per sum, which is inefficient. Balanced BST range queries are complex and slower. DP precomputation is infeasible for dynamic inserts. Trie with prefix sums allows O(k) insert and sum operations.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Trie prefix sums enable O(k) operations [OK]
Hint: Trie with prefix sums supports O(k) insert and sum [OK]
Common Mistakes:
  • Thinking brute force scanning is efficient enough
  • Using BSTs for prefix sums
  • Trying DP precomputation for dynamic keys
2. Given the following code snippet for MapSum, after inserting keys "apple" with value 3 and "app" with value 2, what is the value of node.sum at the trie node corresponding to 'p' (the second character) after the second insert?
easy
A. 3
B. 5
C. 2
D. 0

Solution

  1. Step 1: Trace insert of "apple" with value 3

    Delta = 3 - 0 = 3. Root.sum += 3 -> 3. For each character 'a','p','p','l','e', node.sum += 3. After first insert, node at second 'p' has sum 3.
  2. Step 2: Trace insert of "app" with value 2

    Delta = 2 - 0 = 2. Root.sum += 2 -> 5. For 'a','p','p', node.sum += 2. Node at second 'p' sum was 3, now 3 + 2 = 5.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Sum at second 'p' after both inserts is 5 [OK]
Hint: Sum accumulates delta on each insert per prefix node [OK]
Common Mistakes:
  • Forgetting to add delta on second insert
  • Confusing first and second 'p' nodes
  • Using old value instead of delta
3. Consider the following buggy Trie insert method. Which line contains the subtle bug that causes search to fail for inserted words?
medium
A. Line where node = self.root is assigned
B. Line where node = node.children[ch] is assigned inside the loop
C. Line where isEnd flag should be set but is missing
D. Line where the if condition checks if ch not in node.children

Solution

  1. Step 1: Identify missing isEnd flag set

    After inserting all characters, isEnd must be set true to mark word end. This line is missing.
  2. Step 2: Understand impact on search

    Without isEnd=true, search returns false even if path exists, because node.isEnd remains false.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Missing isEnd assignment causes search failure for inserted words [OK]
Hint: isEnd must be set after inserting entire word [OK]
Common Mistakes:
  • Forgetting to mark isEnd after insertion
4. The following code attempts to find the maximum XOR of two numbers using a bitwise trie. Identify the bug that causes incorrect results or runtime errors for edge cases.
medium
A. Not handling the case when nums has only one element, causing incorrect max_xor
B. Incorrect bit shifting in line extracting bit from num
C. Not updating max_xor after processing each number
D. Using dictionary for children instead of fixed-size array

Solution

  1. Step 1: Consider edge case of single element array

    If nums has only one element, the maximum XOR should be 0, but code does not explicitly handle this and may return incorrect or crash.
  2. Step 2: Check other lines

    Bit shifting and max_xor update lines are correct; using dictionary is valid though less efficient.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Single element input requires special handling to avoid incorrect result [OK]
Hint: Single element arrays need special XOR handling [OK]
Common Mistakes:
  • Assuming input size >= 2 without checks
5. Suppose the autocomplete system must now support returning the top 5 suggestions instead of 3, and the products list can be updated dynamically with insertions. Which modification to the trie-based approach is most appropriate to maintain efficient queries?
hard
A. Increase the suggestions list size to 5 at each node and rebuild the entire trie after each insertion.
B. Store all products at each node and filter top 5 suggestions during query time.
C. Switch to brute force filtering and sorting after each insertion to avoid trie complexity.
D. Use a balanced search tree or heap at each node to maintain top 5 suggestions dynamically during insertions.

Solution

  1. Step 1: Understand dynamic updates and top-K requirement

    Supporting dynamic insertions and top 5 suggestions requires efficient updates and queries without rebuilding the entire trie.
  2. Step 2: Evaluate data structures for suggestions

    Using a balanced tree or min-heap at each node allows maintaining top 5 suggestions dynamically as products are inserted, avoiding costly rebuilds.
  3. Step 3: Reject naive approaches

    Rebuilding trie after each insertion is inefficient. Brute force filtering is too slow. Storing all products at each node wastes space and slows queries.
  4. Final Answer:

    Option D -> Option D
  5. Quick Check:

    Balanced structures enable efficient dynamic top-K maintenance [OK]
Hint: Use balanced structures at nodes for dynamic top-K updates [OK]
Common Mistakes:
  • Rebuilding trie on every insertion
  • Ignoring dynamic update costs
  • Storing all products at nodes
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