Trie (Prefix Tree) Implementation

Data Structures
Medium
Google
106.4K views

Implement the Trie data structure, which supports `insert`, `search`, and `startsWith` operations efficiently. Discuss node structure and traversal.

Why Interviewers Ask This

Google interviewers ask this to evaluate your ability to design efficient, space-optimized data structures for string-heavy workloads. They specifically test if you can balance time complexity against memory usage, as Tries are crucial for autocomplete and search features. This question reveals your understanding of pointer manipulation, edge cases in tree traversal, and whether you prioritize algorithmic efficiency over brute-force solutions.

How to Answer This Question

1. Clarify Requirements: Confirm if the Trie handles only lowercase English letters or needs Unicode support, and verify if it must count occurrences or just existence. 2. Define Node Structure: Propose a class with an array or hash map for children pointers and a boolean flag for 'isEndOfWord'. Mention why an array is faster for fixed alphabets while maps save space for sparse characters. 3. Outline Insert Logic: Explain iterating through characters, creating nodes on demand, and marking the final node. 4. Detail Search Variants: Describe traversing character by character for exact matches versus stopping early for prefix checks. 5. Analyze Complexity: Explicitly state O(M) time where M is word length and O(N * M) space for N words. Conclude by discussing how this scales better than hashing for prefix operations.

Key Points to Cover

  • Explicitly distinguishing between exact search and prefix search logic
  • Choosing between array vs. hash map for children based on alphabet size
  • Correctly handling the creation of new nodes during insertion to avoid null pointer exceptions
  • Stating linear time complexity relative to string length rather than total dataset size
  • Demonstrating awareness of memory overhead trade-offs inherent in tree structures

Sample Answer

I would start by defining a TrieNode class containing a dictionary for children and a boolean flag indicating if a word ends here. For Google's scale, I'd prefer a hash map for children to handle dynamic character sets efficiently, though an array of size 26 works well for standard ASCII. During insertion, I iterate through each character of the input string. If a child node for that character doesn't exist, I create one. I move down the tree until the end, then set the isEnd flag to true. This ensures we don't duplicate storage for common prefixes. For searching, I traverse the tree following the characters. If I hit a null pointer before finishing the string, the word isn't present. For startsWith, the logic is identical, but I simply return true if I successfully reach the last character without needing the isEnd flag. This operation runs in O(K) time, where K is the key length, making it significantly faster than scanning a list of strings. Space complexity is proportional to the total number of unique characters across all inserted words. While this uses more memory than a simple hash set, it is indispensable for real-time autocomplete systems where partial matches are critical. I would also consider adding a counter field to track how many times a word was inserted, which is useful for ranking suggestions.

Common Mistakes to Avoid

  • Confusing the search function with startsWith by requiring the isEnd flag for prefix checks
  • Using a global variable instead of passing references correctly during recursive or iterative traversal
  • Failing to initialize the root node properly, leading to immediate crashes on the first insert
  • Overlooking edge cases like inserting an empty string or searching for a non-existent prefix

Practice This Question with AI

Answer this question orally or via text and get instant AI-powered feedback on your response quality, structure, and delivery.

Start Practicing

Related Interview Questions

Browse all 154 Data Structures questionsBrowse all 87 Google questions