class TrieNode {
constructor() {
this.children = new Map();
this.isWord = false;
}
}
class Trie {
constructor() {
this.root = new TrieNode();
}
insert(word) {
let node = this.root;
for (const char of word) {
if (!node.children.has(char)) {
node.children.set(char, new TrieNode());
}
node = node.children.get(char); // advance node to child
}
node.isWord = true; // mark end of word
}
_dfs(node, prefix, results) {
if (node.isWord) {
results.push(prefix); // found a word
}
for (const [char, child] of node.children) {
this._dfs(child, prefix + char, results); // explore deeper
}
}
autocomplete(prefix) {
let node = this.root;
for (const char of prefix) {
if (!node.children.has(char)) {
return []; // prefix not found
}
node = node.children.get(char); // move to prefix node
}
const results = [];
this._dfs(node, prefix, results); // collect all words
return results;
}
}
// Driver code
const trie = new Trie();
['cat', 'car', 'cart'].forEach(word => trie.insert(word));
const completions = trie.autocomplete('ca');
console.log(completions.join(', '));node = node.children.get(char); // advance node to child
advance node to next letter node to build path
node.isWord = true; // mark end of word
mark current node as a complete word
if (!node.children.has(char)) { return []; }
stop if prefix path missing, no completions
this._dfs(node, prefix, results); // collect all words
collect all words starting from prefix node
if (node.isWord) { results.push(prefix); }
add word to results when word end found