Challenge - 5 Problems
Trie Mastery Badge
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediateOutput of Trie Word Search Result
What is the output of the following Rust code that inserts words into a Trie and searches for a specific word?
DSA Rust
struct TrieNode {
children: [Option<Box<TrieNode>>; 26],
is_end: bool,
}
impl TrieNode {
fn new() -> Self {
Self {
children: Default::default(),
is_end: false,
}
}
}
struct Trie {
root: TrieNode,
}
impl Trie {
fn new() -> Self {
Self {
root: TrieNode::new(),
}
}
fn insert(&mut self, word: &str) {
let mut node = &mut self.root;
for ch in word.chars() {
let idx = (ch as u8 - b'a') as usize;
if node.children[idx].is_none() {
node.children[idx] = Some(Box::new(TrieNode::new()));
}
node = node.children[idx].as_mut().unwrap();
}
node.is_end = true;
}
fn search(&self, word: &str) -> bool {
let mut node = &self.root;
for ch in word.chars() {
let idx = (ch as u8 - b'a') as usize;
if node.children[idx].is_none() {
return false;
}
node = node.children[idx].as_ref().unwrap();
}
node.is_end
}
}
fn main() {
let mut trie = Trie::new();
trie.insert("apple");
trie.insert("app");
trie.insert("bat");
println!("{}", trie.search("app"));
println!("{}", trie.search("apple"));
println!("{}", trie.search("bat"));
println!("{}", trie.search("bath"));
}Attempts:
2 left
💡 Hint
Trace the insertions and check if the search word ends at a node marked as end of a word.
✗ Incorrect
The words 'app', 'apple', and 'bat' are inserted. Searching 'app', 'apple', and 'bat' returns true because they were inserted. Searching 'bath' returns false because it was not inserted.
🧠 Conceptual
intermediateTrie Node Children Representation
In a Trie implementation for lowercase English letters, what is the best way to represent the children nodes of each TrieNode?
Attempts:
2 left
💡 Hint
Consider fixed alphabet size and fast access by index.
✗ Incorrect
Using a fixed-size array of 26 elements allows O(1) access to children nodes for each letter, which is efficient for fixed alphabets like lowercase English letters.
🔧 Debug
advancedIdentify the Bug in Trie Search Method
What error will occur when running this Rust Trie search method if the word contains uppercase letters?
DSA Rust
fn search(&self, word: &str) -> bool { let mut node = &self.root; for ch in word.chars() { let idx = (ch as u8 - b'a') as usize; if node.children[idx].is_none() { return false; } node = node.children[idx].as_ref().unwrap(); } node.is_end }
Attempts:
2 left
💡 Hint
Check how uppercase letters convert to indices.
✗ Incorrect
Uppercase letters have ASCII codes less than 'a', so subtracting 'a' results in a large usize causing index out of bounds panic.
🚀 Application
advancedFind All Words with Given Prefix in Trie
Given a Trie with inserted words, which method correctly collects all words starting with a given prefix?
DSA Rust
fn collect_words(node: &TrieNode, prefix: &mut String, results: &mut Vec<String>) {
if node.is_end {
results.push(prefix.clone());
}
for i in 0..26 {
if let Some(child) = &node.children[i] {
prefix.push((b'a' + i as u8) as char);
collect_words(child, prefix, results);
prefix.pop();
}
}
}
fn words_with_prefix(trie: &Trie, prefix: &str) -> Vec<String> {
let mut node = &trie.root;
for ch in prefix.chars() {
let idx = (ch as u8 - b'a') as usize;
if node.children[idx].is_none() {
return vec![];
}
node = node.children[idx].as_ref().unwrap();
}
let mut results = Vec::new();
let mut prefix_string = prefix.to_string();
collect_words(node, &mut prefix_string, &mut results);
results
}Attempts:
2 left
💡 Hint
After reaching prefix node, explore all child paths recursively.
✗ Incorrect
The method finds the node matching the prefix, then uses DFS to collect all words starting from that node.
❓ Predict Output
expertOutput of Trie Search with Backtracking Word Search
What is the output of this Rust code that uses a Trie to check if a word can be formed by concatenating two words from the Trie?
DSA Rust
struct TrieNode {
children: [Option<Box<TrieNode>>; 26],
is_end: bool,
}
impl TrieNode {
fn new() -> Self {
Self {
children: Default::default(),
is_end: false,
}
}
}
struct Trie {
root: TrieNode,
}
impl Trie {
fn new() -> Self {
Self {
root: TrieNode::new(),
}
}
fn insert(&mut self, word: &str) {
let mut node = &mut self.root;
for ch in word.chars() {
let idx = (ch as u8 - b'a') as usize;
if node.children[idx].is_none() {
node.children[idx] = Some(Box::new(TrieNode::new()));
}
node = node.children[idx].as_mut().unwrap();
}
node.is_end = true;
}
fn search(&self, word: &str) -> bool {
let mut node = &self.root;
for ch in word.chars() {
let idx = (ch as u8 - b'a') as usize;
if node.children[idx].is_none() {
return false;
}
node = node.children[idx].as_ref().unwrap();
}
node.is_end
}
fn can_form_by_two_words(&self, word: &str) -> bool {
fn backtrack(trie: &Trie, word: &str, start: usize, count: usize) -> bool {
if start == word.len() {
return count == 2;
}
let mut node = &trie.root;
for i in start..word.len() {
let idx = (word.as_bytes()[i] - b'a') as usize;
if node.children[idx].is_none() {
return false;
}
node = node.children[idx].as_ref().unwrap();
if node.is_end {
if backtrack(trie, word, i + 1, count + 1) {
return true;
}
}
}
false
}
backtrack(self, word, 0, 0)
}
}
fn main() {
let mut trie = Trie::new();
trie.insert("cat");
trie.insert("dog");
trie.insert("cats");
trie.insert("sand");
trie.insert("and");
println!("{}", trie.can_form_by_two_words("catsand"));
println!("{}", trie.can_form_by_two_words("catdog"));
println!("{}", trie.can_form_by_two_words("catsanddog"));
}Attempts:
2 left
💡 Hint
Check if the word can be split into exactly two words from the Trie.
✗ Incorrect
"catsand" can be split as "cats" + "and" (both in Trie), returns true.
"catdog" can be split as "cat" + "dog", returns true.
"catsanddog" requires more than two words, returns false.
