Prefix Search Using Trie in DSA Python - Time & Space Complexity
We want to understand how fast we can find words that start with a given prefix using a Trie.
How does the search time change as the prefix or stored words grow?
Analyze the time complexity of the following prefix search code in a Trie.
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def starts_with(self, prefix: str) -> bool:
node = self.root
for char in prefix:
if char not in node.children:
return False
node = node.children[char]
return True
This code checks if any word in the Trie starts with the given prefix.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each character of the prefix.
- How many times: Once for each character in the prefix (length m).
The search time grows with the length of the prefix, not the number of words stored.
| Input Size (prefix length m) | Approx. Operations |
|---|---|
| 10 | About 10 character checks |
| 100 | About 100 character checks |
| 1000 | About 1000 character checks |
Pattern observation: The operations increase linearly as the prefix length increases.
Time Complexity: O(m)
This means the search time depends only on the prefix length, not on how many words are in the Trie.
[X] Wrong: "The search time depends on the total number of words stored in the Trie."
[OK] Correct: The search only follows the prefix characters down the Trie nodes, so it depends on prefix length, not total words.
Knowing how Trie prefix search scales helps you explain efficient word lookup in real apps like autocomplete or spell checkers.
"What if we changed the prefix search to return all words starting with the prefix? How would the time complexity change?"
Practice
Solution
Step 1: Understand Trie usage
A Trie stores characters of words in a tree structure, allowing quick prefix lookups.Step 2: Identify prefix search goal
Prefix search means finding all words that start with a given prefix efficiently.Final Answer:
To efficiently find all words starting with a given prefix -> Option DQuick Check:
Trie = prefix search efficiency [OK]
- Confusing Trie with sorting data structure
- Thinking Trie is for arithmetic
- Assuming Trie stores whole words only
Solution
Step 1: Understand Trie children structure
Trie children are usually stored in a dictionary mapping characters to TrieNode objects.Step 2: Correct insertion syntax
We check if character exists; if not, create new TrieNode and assign it to children dictionary.Final Answer:
node.children[char] = TrieNode() if char not in node.children else node.children[char] -> Option BQuick Check:
Insert word by mapping char to TrieNode [OK]
- Using list methods like append or add on dictionary
- Assigning character instead of TrieNode
- Not checking if child node exists before insertion
trie.starts_with('app')?
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.is_end = True
def starts_with(self, prefix):
node = self.root
for char in prefix:
if char not in node.children:
return False
node = node.children[char]
return True
trie = Trie()
trie.insert('apple')
trie.insert('app')
print(trie.starts_with('app'))Solution
Step 1: Insert words 'apple' and 'app'
Both words share prefix 'app', so nodes for 'a', 'p', 'p' exist in Trie.Step 2: Check starts_with('app')
Function checks each character in 'app' exists in children; all found, so returns True.Final Answer:
True -> Option CQuick Check:
Prefix 'app' exists in Trie = True [OK]
- Confusing starts_with with full word search
- Expecting False because 'app' is prefix, not full word
- Ignoring that 'app' was inserted
starts_with method and select the correct fix:
def starts_with(self, prefix):
node = self.root
for char in prefix:
if char in node.children:
node = node.children[char]
else:
return True
return FalseSolution
Step 1: Analyze current else return
Currently, if char not found, method returns True incorrectly; should return False.Step 2: Correct return values
Return False inside else (prefix not found), and True after loop (prefix fully matched).Final Answer:
Return False inside else, return True after loop -> Option AQuick Check:
Prefix missing = False, prefix found = True [OK]
- Returning True when prefix char missing
- Returning False after loop instead of True
- Confusing else and after loop returns
"car". Which approach correctly extends the prefix search to list all such words?Solution
Step 1: Locate prefix node in Trie
Traverse Trie nodes for 'c', 'a', 'r' to reach prefix node.Step 2: Recursively collect words from prefix node
From prefix node, explore all child nodes to build and collect complete words starting with 'car'.Final Answer:
Traverse to node of 'car' prefix, then recursively collect all words from that node -> Option AQuick Check:
Prefix node + recursion = all words with prefix [OK]
- Checking all words instead of using Trie structure
- Inserting prefix as word incorrectly
- Using unrelated data structures like hash map
Ready to prove it?
Pass the test and this pattern moves unknown
