Word Search in Trie in DSA Python - Time & Space Complexity
We want to know how long it takes to find a word in a Trie as the word length changes.
How does the search time grow when the word gets longer?
Analyze the time complexity of the following code snippet.
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def search(self, word: str) -> bool:
node = self.root
for char in word:
if char not in node.children:
return False
node = node.children[char]
return node.is_end
This code searches for a word in a Trie by checking each character step-by-step.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each character of the word.
- How many times: Exactly once per character in the word (word length).
As the word gets longer, the search checks more characters one by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 character checks |
| 100 | About 100 character checks |
| 1000 | About 1000 character checks |
Pattern observation: The number of operations grows directly with the word length.
Time Complexity: O(n)
This means the search time grows linearly with the length of the word you are looking for.
[X] Wrong: "Searching a word in a Trie takes constant time because it's a tree."
[OK] Correct: The search depends on the word length, so longer words take more steps, not always constant time.
Understanding this helps you explain how Tries speed up searches compared to checking every word, and shows you can analyze step-by-step costs clearly.
"What if the Trie stored words with a fixed maximum length? How would that affect the time complexity?"
Practice
Trie data structure in word search problems?Solution
Step 1: Understand the Trie structure
A Trie stores characters of words in a tree-like structure where each node represents a character.Step 2: Identify the main use in word search
This structure allows quick lookup of words by their prefixes, making prefix-based search very efficient.Final Answer:
To store words in a way that allows fast prefix-based search -> Option AQuick Check:
Trie = fast prefix search [OK]
- Confusing Trie with sorting structures
- Thinking Trie stores words as linked lists
- Assuming Trie compresses words into strings
ch exists as a child node in a Trie node's children dictionary named children?Solution
Step 1: Recall Python dictionary membership check
In Python, to check if a key exists in a dictionary, usekey in dict.Step 2: Identify the correct syntax
if ch in children:is the correct and most Pythonic way to check key existence.Final Answer:
if ch in children: -> Option CQuick Check:
Python dict key check = 'in' keyword [OK]
- Using deprecated has_key() method
- Checking keys() explicitly which is slower
- Using non-existent contains() method
def search_word(root, word):
node = root
for ch in word:
if ch not in node.children:
return False
node = node.children[ch]
return node.is_end_of_word
# Trie nodes and root are properly initialized
result = search_word(root, 'cat')
If the Trie contains the words ['car', 'cat', 'cap'], what will be the value of result?Solution
Step 1: Trace the search for 'cat'
The function checks each character 'c', 'a', 't' in the Trie nodes. Since 'cat' is inserted, all characters exist and the last node marks end of word.Step 2: Return the end of word flag
Because 'cat' is a complete word in the Trie,node.is_end_of_wordis True, so the function returns True.Final Answer:
True -> Option DQuick Check:
Word 'cat' found = True [OK]
- Returning True without checking end_of_word flag
- Assuming partial prefix means word exists
- Confusing missing character with KeyError
def search_word(root, word):
node = root
for ch in word:
if ch not in node:
return False
node = node[ch]
return node.is_end_of_word
Solution
Step 1: Analyze membership check
The code checksif ch not in node, butnodeis an object, not a dictionary. It should checknode.children.Step 2: Analyze node traversal
Similarly,node = node[ch]is incorrect; it should benode = node.children[ch]to access the child node.Final Answer:
Both B and C are correct -> Option BQuick Check:
Access children dict properly = Both fixes needed [OK]
- Checking keys on node object instead of children dict
- Assigning node = node[ch] instead of node.children[ch]
- Ignoring attribute errors from wrong access
prefix. Which modification to the standard word search function below will correctly check for prefix existence?
def starts_with(root, prefix):
node = root
for ch in prefix:
if ch not in node.children:
return False
node = node.children[ch]
# What to return here?
Solution
Step 1: Understand prefix search logic
To check if any word starts with the prefix, we only need to confirm all prefix characters exist in the Trie.Step 2: Decide return value after loop
If all characters are found, return True immediately. We do not need to check if the node marks end of a word.Final Answer:
Return True immediately after loop ends -> Option AQuick Check:
Prefix found = True [OK]
- Returning is_end_of_word which fails for prefixes not full words
- Checking children existence unnecessarily
- Restricting prefix length to 1
Ready to prove it?
Pass the test and this pattern moves unknown
