0
0
DSA Javascriptprogramming

Trie vs Hash Map for Prefix Matching in DSA Javascript - Trade-offs & Analysis

Choose your learning style9 modes available
Mental Model
A trie stores words by their letters in a tree, making prefix search fast. A hash map stores whole words as keys, so prefix search needs extra work.
Analogy: Imagine a phone book organized by first letter, then second letter, and so on (trie), versus a list of full names where you have to check each name to find those starting with a prefix (hash map).
Trie:
root
 ├─ a
 │   ├─ p
 │   │   ├─ p
 │   │   │   └─ l
 │   │   │       └─ e (end)
 └─ b
     └─ a
         └─ t (end)

Hash Map:
{
  "apple": true,
  "bat": true
}
Dry Run Walkthrough
Input: words: ["apple", "bat"], prefix to search: "ap"
Goal: Find if any word starts with prefix "ap" using trie and hash map
Step 1: Insert "apple" into trie by creating nodes for each letter
root -> a -> p -> p -> l -> e [end]
Hash Map: {"apple": true}
Why: Build trie structure to represent "apple" letter by letter
Step 2: Insert "bat" into trie by creating nodes for each letter
root -> a -> p -> p -> l -> e [end]
      └─ b -> a -> t [end]
Hash Map: {"apple": true, "bat": true}
Why: Add second word to trie sharing no prefix with "apple"
Step 3: Search prefix "ap" in trie by following nodes a -> p
At node p after root -> a -> p
Hash Map keys: ["apple", "bat"]
Why: Traverse trie nodes matching prefix letters
Step 4: Confirm prefix exists in trie since nodes for 'a' and 'p' found
Prefix "ap" found in trie
Hash Map: Need to check keys for prefix
Why: Trie structure directly shows prefix presence
Step 5: Search prefix "ap" in hash map by checking each key
Check "apple" starts with "ap" -> true
Check "bat" starts with "ap" -> false
Why: Hash map requires scanning keys for prefix match
Step 6: Return true for prefix found in both trie and hash map
Result: prefix "ap" exists
Why: Both data structures confirm prefix presence
Result:
Trie:
root -> a -> p -> p -> l -> e [end]
      └─ b -> a -> t [end]
Prefix "ap" found
Hash Map: {"apple": true, "bat": true}
Prefix "ap" found by scanning keys
Annotated Code
DSA Javascript
class TrieNode {
  constructor() {
    this.children = new Map();
    this.isEnd = 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 to child node
    }
    node.isEnd = true; // mark end of word
  }

  startsWith(prefix) {
    let node = this.root;
    for (const char of prefix) {
      if (!node.children.has(char)) {
        return false; // prefix not found
      }
      node = node.children.get(char); // advance to next node
    }
    return true; // prefix found
  }
}

// Hash Map prefix search
function hashMapPrefixSearch(map, prefix) {
  for (const key of map.keys()) {
    if (key.startsWith(prefix)) {
      return true; // prefix found
    }
  }
  return false; // prefix not found
}

// Driver code
const words = ["apple", "bat"];
const prefix = "ap";

// Build trie
const trie = new Trie();
for (const word of words) {
  trie.insert(word);
}

// Build hash map
const map = new Map();
for (const word of words) {
  map.set(word, true);
}

// Search prefix
console.log("Trie prefix found:", trie.startsWith(prefix));
console.log("Hash Map prefix found:", hashMapPrefixSearch(map, prefix));
node = node.children.get(char); // advance to child node
advance node to next letter node to build or traverse trie
node.isEnd = true; // mark end of word
mark current node as end of a valid word
if (!node.children.has(char)) { return false; }
stop search if prefix letter missing in trie
for (const key of map.keys()) { if (key.startsWith(prefix)) { return true; } }
scan all keys in hash map to find prefix match
OutputSuccess
Trie prefix found: true Hash Map prefix found: true
Complexity Analysis
Time: Trie prefix search: O(m) where m is prefix length, because we follow nodes letter by letter. Hash map prefix search: O(n * m) where n is number of keys and m is prefix length, because we check each key's start.
Space: Trie uses O(total letters in all words) for nodes, which can be less if words share prefixes. Hash map uses O(n) for storing all words as keys.
vs Alternative: Trie is faster for prefix queries because it avoids scanning all keys, while hash map requires checking each key, making it slower for large datasets.
Edge Cases
Empty prefix string
Trie returns true immediately since empty prefix matches all words; hash map also returns true since all keys start with empty string
DSA Javascript
for (const char of prefix) { if (!node.children.has(char)) { return false; } }
Prefix not present in any word
Trie returns false when missing node found; hash map returns false after scanning all keys
DSA Javascript
if (!node.children.has(char)) { return false; }
Words with shared prefixes
Trie nodes are shared, saving space and speeding prefix search; hash map stores all keys separately
DSA Javascript
node = node.children.get(char);
When to Use This Pattern
When you need to quickly find if any word starts with a given prefix, especially in large word sets, reach for the trie pattern because it allows fast prefix traversal without scanning all words.
Common Mistakes
Mistake: Trying to do prefix search directly on hash map keys without scanning all keys
Fix: Implement a loop to check each key's start or use a trie for efficient prefix queries
Mistake: Not marking end of word in trie, causing incorrect prefix or word detection
Fix: Set isEnd = true at the last node of inserted word
Summary
Compares trie and hash map for checking if any word starts with a prefix.
Use trie for efficient prefix search in large word collections; hash map is simpler but slower for prefix queries.
Trie stores words letter by letter in a tree, enabling fast prefix traversal without scanning all words.