Longest Word in Dictionary Using Trie in DSA Python - Time & Space Complexity
We want to understand how the time needed to find the longest word in a dictionary using a Trie grows as the dictionary size grows.
Specifically, how the operations scale when inserting words and searching for the longest valid word.
Analyze the time complexity of the following code snippet.
class TrieNode:
def __init__(self):
self.children = {}
self.is_word = 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_word = True
def longest_word(self):
result = ""
def dfs(node, path):
nonlocal result
if len(path) > len(result):
result = path
for char in sorted(node.children.keys()):
child = node.children[char]
if child.is_word:
dfs(child, path + char)
dfs(self.root, "")
return result
words = ["a", "app", "apple", "apply", "ap", "banana"]
trie = Trie()
for w in words:
trie.insert(w)
print(trie.longest_word())
This code builds a Trie from a list of words, then finds the longest word where every prefix is also a word in the Trie.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Inserting each word character by character into the Trie and traversing nodes during DFS.
- How many times: Insert runs once per word, each character processed once; DFS visits nodes where prefixes form words.
As the number of words and their lengths grow, the insertions and DFS traversal grow roughly with total characters.
| Input Size (n words) | Approx. Operations |
|---|---|
| 10 (avg length 5) | ~50 insert + DFS steps |
| 100 (avg length 5) | ~500 insert + DFS steps |
| 1000 (avg length 5) | ~5000 insert + DFS steps |
Pattern observation: Operations grow roughly proportional to total characters in all words combined.
Time Complexity: O(N * L)
This means the time grows linearly with the number of words (N) times the average length of each word (L).
[X] Wrong: "The search for the longest word is constant time because we just follow Trie nodes."
[OK] Correct: The search uses DFS and may visit many nodes depending on the Trie size, so it depends on total characters stored, not constant time.
Understanding this time complexity helps you explain how Trie operations scale and why they are efficient for prefix-based problems.
"What if we changed the DFS to BFS for finding the longest word? How would the time complexity change?"
Practice
Solution
Step 1: Understand Trie usage
A Trie stores words by breaking them into characters and linking nodes for prefixes.Step 2: Relate Trie to longest word search
This structure allows quick prefix checks, which helps find the longest word built from other words.Final Answer:
To efficiently store and search words by their prefixes -> Option AQuick Check:
Trie = prefix search [OK]
- Thinking Trie sorts words alphabetically
- Confusing Trie with simple lists
- Assuming Trie counts words only
Solution
Step 1: Understand Trie children structure
Trie children are stored in a dictionary mapping characters to TrieNode objects.Step 2: Correct insertion method
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 AQuick Check:
Insert uses dictionary with TrieNode [OK]
- Using add() or append() on dictionary
- Assigning character instead of TrieNode
- Not checking if child exists before insertion
["a", "app", "apple", "apply", "ap"], what is the longest word that can be built one character at a time using the Trie method?Solution
Step 1: Check each word's prefixes
Words must have all prefixes present: "a", "ap", "app" are present; "apple" and "apply" require "appl" which is missing.Step 2: Identify longest valid word
"app" is the longest word where all prefixes exist in the list.Final Answer:
"app" -> Option BQuick Check:
Longest word with all prefixes = "app" [OK]
- Assuming "apple" or "apply" are valid without "appl"
- Ignoring prefix requirement
- Choosing shortest word instead
for word in words:
node = root
for char in word:
if char not in node.children:
node.children[char] = TrieNode
node = node.children[char]
node.is_word = TrueSolution
Step 1: Identify object creation mistake
TrieNode is a class; to create an object, parentheses () are needed.Step 2: Understand impact of missing parentheses
Without (), node.children[char] stores the class itself, not an instance, causing errors on further access.Final Answer:
TrieNode should be called with parentheses to create an instance -> Option DQuick Check:
Instantiate TrieNode with () [OK]
- Forgetting parentheses when creating objects
- Setting flags in wrong loop place
- Resetting root incorrectly inside loops
["w", "wo", "wor", "worl", "world", "banana", "ban", "bana", "banan"]. Using a Trie, which word will be returned as the longest word built one character at a time from other words in the list?Solution
Step 1: Verify prefix chains for each candidate
"world" prefixes: "w", "wo", "wor", "worl", "world" all exist; "banana" and "banan" missing prefixes like "b", "ba"; "worl" is shorter than "world".Step 2: Choose longest word with all prefixes present
"world" is longest with all prefixes present in the list.Final Answer:
"world" -> Option CQuick Check:
Longest word with full prefix chain = "world" [OK]
- Choosing "banana" without full prefix chain
- Ignoring prefix requirement for "banan"
- Picking shorter word "worl" over "world"
Ready to prove it?
Pass the test and this pattern moves unknown
