Trie Search Operation in DSA Rust - Time & Space Complexity
We want to understand how long it takes to find a word in a trie. This helps us see how efficient the search is as words get longer.
The question is: How does search time grow when the word length changes?
Analyze the time complexity of the following code snippet.
struct TrieNode {
children: [Option; 26],
is_end: bool,
}
impl TrieNode {
fn search(&self, word: &str) -> bool {
let mut node = self;
for ch in word.chars() {
let index = (ch as usize) - ('a' as usize);
match &node.children[index] {
Some(next_node) => node = next_node,
None => return false,
}
}
node.is_end
}
}
This code checks if a word exists in a trie by following each letter's path from the root.
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 nodes one by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 checks |
| 100 | 100 checks |
| 1000 | 1000 checks |
Pattern observation: The number of checks 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 time proportional to the number of words stored."
[OK] Correct: The search only depends on the word length, not how many words are in the trie.
Knowing trie search time helps you explain why tries are great for fast word lookups, especially when many words share prefixes.
"What if the trie stored Unicode characters instead of just lowercase letters? How would the time complexity change?"
Practice
search operation in a Trie data structure do?Solution
Step 1: Understand the purpose of search in Trie
The search operation is designed to check if a specific word is present in the Trie structure.Step 2: Differentiate from other operations
Insertion adds words, deletion removes words, and counting totals words, but search only checks existence.Final Answer:
Checks if a given word exists in the Trie -> Option CQuick Check:
Search = Check existence [OK]
- Confusing search with insert operation
- Thinking search deletes words
- Assuming search counts words
Solution
Step 1: Identify correct method receiver and parameters
The search method should borrow self immutably (&self) and take a string slice (&str) for the word to search.Step 2: Confirm return type
Search returns a boolean indicating presence, so return type must be bool.Final Answer:
fn search(&self, word: &str) -> bool -> Option AQuick Check:
Immutable borrow + &str + bool return [OK]
- Using mutable borrow &mut self unnecessarily
- Returning wrong type like String or usize
- Taking owned String instead of &str
let mut trie = Trie::new();
trie.insert("car");
trie.insert("cat");
trie.insert("cap");
println!("{}", trie.search("cat"));Solution
Step 1: Analyze inserted words
The words "car", "cat", and "cap" are inserted into the Trie, so "cat" is present.Step 2: Check search output for "cat"
Searching "cat" should return true because it was inserted.Final Answer:
true -> Option DQuick Check:
Inserted words include "cat" so search returns true [OK]
- Assuming search returns false if similar words exist
- Confusing insert and search methods
- Expecting runtime errors without reason
fn search(&self, word: &str) -> bool {
let mut node = &self.root;
for ch in word.chars() {
if !node.children.contains_key(&ch) {
return false;
}
node = node.children.get(&ch).unwrap();
}
true
}Solution
Step 1: Understand search logic
The code checks if each character exists in children nodes, moving down the Trie.Step 2: Check final return condition
It returns true after loop without verifying if current node marks end of a complete word.Step 3: Identify bug
This causes search to return true for prefixes that are not full words.Final Answer:
Returns true even if word is a prefix but not complete word -> Option BQuick Check:
Missing end-of-word check causes false positives [OK]
- Ignoring end-of-word marker in search
- Assuming unwrap() always panics here
- Misunderstanding iteration over chars
Solution
Step 1: Understand wildcard '.' meaning
The '.' can match any single character, so search must consider all possible children at that position.Step 2: Choose search strategy
Recursion allows exploring all children nodes when '.' is found, checking all paths.Step 3: Evaluate other options
Replacing '.' with all alphabets is inefficient; ignoring '.' is incorrect; hash map for positions doesn't solve matching.Final Answer:
Use recursion to explore all children nodes when '.' is encountered -> Option AQuick Check:
Recursion handles wildcards by branching [OK]
- Ignoring wildcard meaning
- Trying to replace '.' with all letters before search
- Skipping recursive exploration
Ready to prove it?
Pass the test and this pattern moves unknown
