Word Search in Trie in DSA C++ - Time & Space Complexity
We want to understand how long it takes to find a word in a Trie data structure.
Specifically, how the search time changes as the word length grows.
Analyze the time complexity of the following code snippet.
bool searchWord(TrieNode* root, const std::string& word) {
TrieNode* current = root;
for (char c : word) {
int index = c - 'a';
if (!current->children[index]) {
return false;
}
current = current->children[index];
}
return current->isEndOfWord;
}
This code checks if a given word exists in the Trie by following nodes for each letter.
- Primary operation: Loop through each character of the word.
- How many times: Exactly once per character in the word.
The time grows directly with the length of the word we search for.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks |
| 100 | About 100 checks |
| 1000 | About 1000 checks |
Pattern observation: The operations increase linearly as the word length increases.
Time Complexity: O(n)
This means the search time grows in a straight line with the word length.
[X] Wrong: "Searching a word in a Trie takes constant time regardless of word length."
[OK] Correct: Each letter must be checked one by one, so longer words take more time.
Knowing how Trie search scales helps you explain efficient word lookups clearly and confidently.
"What if the Trie stored words with uppercase letters too? How would the time complexity change?"
Practice
Trie data structure in word search problems?Solution
Step 1: Understand Trie structure
A Trie stores characters of words in a tree where each node represents a character, allowing prefix sharing.Step 2: Identify Trie use in word search
Because words share prefixes, Trie allows fast prefix-based search, making word search efficient.Final Answer:
To efficiently store and search words by their prefixes -> Option CQuick Check:
Trie = prefix search [OK]
- Confusing Trie with sorting structures
- Thinking Trie stores words linearly
- Assuming Trie is for arithmetic
Solution
Step 1: Check Trie node structure for word search
Trie nodes typically have an array of pointers for 26 letters and a boolean to mark word end.Step 2: Match with options
class TrieNode { public: TrieNode* children[26]; bool isEndOfWord; }; matches this structure exactly with children array and isEndOfWord flag.Final Answer:
class TrieNode { public: TrieNode* children[26]; bool isEndOfWord; }; -> Option AQuick Check:
Trie node = children array + end flag [OK]
- Using linked list pointers instead of array
- Using vector<int> instead of pointers
- Confusing binary tree node with Trie node
class TrieNode {
public:
TrieNode* children[26] = {nullptr};
bool isEndOfWord = false;
};
class Trie {
public:
TrieNode* root;
Trie() { root = new TrieNode(); }
void insert(string word) {
TrieNode* node = root;
for (char c : word) {
int index = c - 'a';
if (!node->children[index])
node->children[index] = new TrieNode();
node = node->children[index];
}
node->isEndOfWord = true;
}
bool search(string word) {
TrieNode* node = root;
for (char c : word) {
int index = c - 'a';
if (!node->children[index])
return false;
node = node->children[index];
}
return node->isEndOfWord;
}
};
int main() {
Trie trie;
trie.insert("cat");
trie.insert("car");
trie.insert("dog");
cout << (trie.search("cat") ? "Found" : "Not Found") << endl;
return 0;
}Solution
Step 1: Insert words "cat", "car", "dog" into Trie
Each word is inserted character by character, creating nodes and marking end of word for last character.Step 2: Search for "cat" in Trie
Traversal finds nodes for 'c', 'a', 't' and confirms isEndOfWord is true, so returns true.Final Answer:
Found -> Option BQuick Check:
Inserted word found = Found [OK]
- Not marking isEndOfWord true on insert
- Returning true without checking end flag
- Off-by-one errors in indexing
bool search(string word) {
TrieNode* node = root;
for (char c : word) {
int index = c - 'a';
if (node->children[index])
return false;
node = node->children[index];
}
return node->isEndOfWord;
}Solution
Step 1: Analyze the if condition inside loop
The condition 'if (node->children[index]) return false;' wrongly returns false if child exists, which is opposite logic.Step 2: Correct the condition to check if child does NOT exist
It should be 'if (!node->children[index]) return false;' to return false when path breaks.Final Answer:
Change 'if (node->children[index])' to 'if (!node->children[index])' -> Option DQuick Check:
Check for missing child = return false [OK]
- Returning false when child exists
- Ignoring null pointer checks
- Incorrect index calculation
Solution
Step 1: Insert all words into Trie
Each word is inserted character by character, building a prefix tree.Step 2: Traverse Trie nodes for prefix "app"
Follow nodes for 'a', 'p', 'p' to reach prefix node, then collect all words below it.Step 3: Collect descendant words
Perform DFS or BFS from prefix node to gather all words starting with "app" efficiently.Final Answer:
Insert all words into Trie, then traverse nodes for 'a'->'p'->'p' and collect all descendant words -> Option AQuick Check:
Trie prefix traversal + collect descendants = Insert all words into Trie, then traverse nodes for 'a'->'p'->'p' and collect all descendant words [OK]
- Using sorting instead of Trie for prefix search
- Checking prefix by substring on all words
- Scanning linked list inefficiently
Ready to prove it?
Pass the test and this pattern moves unknown
