Think about how each data structure organizes keys and how that affects searching by starting letters.
A Trie stores strings character by character in a tree, making it easy to find all words sharing a prefix by traversing the tree. A Hash Map stores whole keys and cannot efficiently find keys by partial prefixes.
class TrieNode { children: Map<string, TrieNode> = new Map(); isWord = false; } class Trie { root = new TrieNode(); insert(word: string) { 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)!; } node.isWord = true; } startsWith(prefix: string): boolean { let node = this.root; for (const char of prefix) { if (!node.children.has(char)) return false; node = node.children.get(char)!; } return true; } } const trie = new Trie(); trie.insert('apple'); trie.insert('app'); const hashMap = new Map<string, boolean>(); hashMap.set('apple', true); hashMap.set('app', true); console.log(trie.startsWith('app')); console.log(hashMap.has('app')); console.log(hashMap.has('ap')); console.log(trie.startsWith('ap'));
Check how Trie and Hash Map handle prefixes and exact keys differently.
Trie.startsWith('app') returns true because 'app' is a prefix in the Trie. Hash Map.has('app') returns true because 'app' is a key. Hash Map.has('ap') returns false because 'ap' is not a key. Trie.startsWith('ap') returns true because 'ap' is a prefix of inserted words.
class TrieNode { children: {[key: string]: TrieNode} = {}; isWord = false; } class Trie { root = new TrieNode(); insert(word: string) { let node = this.root; for (const char of word) { if (!node.children[char]) { node.children[char] = new TrieNode(); } node = node.children[char]; } node.isWord = true; } startsWith(prefix: string): boolean { let node = this.root; for (const char of prefix) { if (!node.children[char]) return false; node = node.children[char]; } return true; } } const trie = new Trie(); trie.insert('hello'); console.log(trie.startsWith('hel'));
Think about what startsWith should return after successfully finding the prefix path.
startsWith should return true if the prefix path exists, regardless of whether the prefix itself is a complete word. Returning node.isWord causes false for prefixes that are not complete words.
Think about how words with common beginnings are stored in each structure.
Trie shares nodes for common prefixes, reducing memory for overlapping parts. Hash Map stores each key fully, so it uses more memory when many words share prefixes.
Consider how each data structure organizes and accesses keys related by prefixes.
Trie nodes represent characters and link to children, so after reaching the prefix node, all words with that prefix are descendants. Hash Map stores keys independently, so finding all keys with a prefix requires checking every key, which is inefficient.