📖 Scenario: You are building a simple search feature for a phone contact list. Users want to find contacts quickly by typing the first few letters of a name.Two common ways to do this are using a Trie (a tree-like structure) or a Hash Map (a dictionary). This project will help you understand how to store and find names by their prefixes using both methods.
🎯 Goal: You will create a list of contact names, set up a prefix to search for, then write code to find all contacts starting with that prefix using a Hash Map and a Trie. Finally, you will print the matching contacts.
📋 What You'll Learn
Create a list of contact names exactly as given
Create a prefix string variable to search
Write a function to find contacts starting with the prefix using a Hash Map
Write a Trie class with insert and prefix search methods
Use the Trie to find contacts starting with the prefix
Print the results from both methods
💡 Why This Matters
🌍 Real World
Prefix matching is used in search bars, autocomplete features, and contact lists to quickly find items starting with typed letters.
💼 Career
Understanding Tries and Hash Maps helps in building efficient search features and is a common topic in coding interviews.
Progress0 / 4 steps
1
Create the contact list
Create a variable called contacts as an array of strings with these exact names: 'Alice', 'Bob', 'Alfred', 'Bobby', 'Albert'
DSA Typescript
Hint
Use square brackets to create an array and include the names as strings separated by commas.
2
Set the prefix to search
Create a variable called prefix and set it to the string 'Al'
DSA Typescript
Hint
Use const prefix: string = 'Al'; to create the prefix variable.
3
Find contacts with prefix using Hash Map
Write a function called findWithHashMap that takes contacts and prefix as parameters and returns an array of contacts starting with prefix. Use a for loop to check each contact with startsWith method.
DSA Typescript
Hint
Use a loop from 0 to contacts.length and check if each contact starts with prefix. If yes, add it to result array.
4
Build Trie and print results
Define a class TrieNode with a children map and isEnd boolean. Define a class Trie with insert and startsWith methods. Insert all contacts into the Trie. Use startsWith to find contacts starting with prefix. Then print the results from findWithHashMap and Trie search using console.log.
DSA Typescript
Hint
Build the Trie by inserting each contact. Use a helper DFS function to collect all words starting with the prefix. Print both results arrays.
Practice
(1/5)
1. Which data structure is generally more efficient for prefix matching in a large set of strings?
easy
A. Trie, because it stores prefixes explicitly and allows fast prefix queries
B. Hash Map, because it stores keys with constant time lookup
C. Array, because it stores elements in order
D. Linked List, because it allows sequential access
Solution
Step 1: Understand prefix matching requirements
Prefix matching means finding all strings that start with a given prefix efficiently.
Step 2: Compare Trie and Hash Map for prefix queries
Trie stores prefixes explicitly in its structure, allowing quick traversal to all words sharing a prefix. Hash Map only allows exact key lookups, not prefix searches.
Final Answer:
Trie, because it stores prefixes explicitly and allows fast prefix queries -> Option A
Quick Check:
Prefix matching = Trie [OK]
Hint: Trie stores prefixes; Hash Map does not support prefix search [OK]
Assuming arrays or linked lists are efficient for prefix queries
2. Which of the following TypeScript code snippets correctly initializes a Trie node for prefix matching?
easy
A. class TrieNode { children: object = {}; isEnd: number = 0; }
B. class TrieNode { children: string[] = []; isEnd: boolean = true; }
C. class TrieNode { children: Map = new Map(); isEnd: boolean = false; }
D. class TrieNode { children: Map = new Map(); isEnd: boolean = false; }
Solution
Step 1: Identify correct data types for TrieNode properties
Children should map characters (string) to TrieNode objects. isEnd should be boolean to mark word end.
Step 2: Check each option's correctness
class TrieNode { children: Map = new Map(); isEnd: boolean = false; } uses Map and boolean isEnd, which is correct. Others use wrong types or incorrect isEnd values.
Final Answer:
class TrieNode { children: Map = new Map(); isEnd: boolean = false; } -> Option C
Quick Check:
TrieNode children = Map [OK]
Hint: Trie children map chars to nodes; isEnd is boolean [OK]
Common Mistakes:
Using array instead of Map for children
Setting isEnd as number instead of boolean
Mapping children with wrong key or value types
3. What will be the output of the following TypeScript code snippet?
Map.has(key) returns true only if exact key exists. 'app' and 'apple' are keys, 'appl' is not.
Step 2: Evaluate console.log outputs
map.has('app') is true; map.has('appl') is false because 'appl' is not a key.
Final Answer:
true\nfalse -> Option D
Quick Check:
Exact keys only: 'app' true, 'appl' false [OK]
Hint: Map.has checks exact keys, not prefixes [OK]
Common Mistakes:
Assuming map.has supports prefix matching
Confusing keys 'appl' and 'apple'
Expecting true for partial keys
4. Consider this buggy TypeScript Trie insert method:
insert(word: string) {
let node = this.root;
for (let char of word) {
if (!node.children.has(char)) {
node.children.set(char, new TrieNode());
}
node = node.children.get(char);
}
node.isEnd = true;
}
What is the main issue causing a runtime error?
medium
A. node.children.get(char) can return undefined, causing assignment to node to fail
B. The loop variable char is not declared properly
C. The isEnd property is set before the loop
D. The root node is not initialized
Solution
Step 1: Analyze node.children.get(char) usage
Even after checking node.children.has(char), node.children.get(char) can theoretically return undefined if the Map is modified concurrently or due to incorrect initialization.
Step 2: Identify runtime error cause
Assigning undefined to node causes subsequent property access to fail, leading to runtime error.
Final Answer:
node.children.get(char) can return undefined, causing assignment to node to fail -> Option A
Quick Check:
Ensure node.children.get(char) is not undefined before assignment [OK]
Hint: Check that node.children.get(char) returns a valid TrieNode before assignment [OK]
Overlooking need for root initialization in constructor
Assuming object-style children access instead of Map methods
5. You want to implement a prefix search feature that returns all words starting with a given prefix from a large dictionary. Which approach is best and why?
// Approach 1: Store all words in a Hash Map and check each key for prefix match
// Approach 2: Build a Trie from all words and traverse to prefix node to collect matches
hard
A. Approach 1 is better because Hash Map lookups are O(1) and prefix checks are fast
B. Approach 2 is better because Trie traversal to prefix node is efficient and collects matches quickly
C. Both approaches are equally efficient for prefix search
D. Neither approach works well; use a sorted array with binary search instead
Solution
Step 1: Evaluate Approach 1 (Hash Map with prefix checks)
Hash Map allows O(1) exact lookups but requires checking every key for prefix, which is O(n) and inefficient for large data.
Step 2: Evaluate Approach 2 (Trie traversal)
Trie stores prefixes explicitly; traversing to prefix node is O(k) where k is prefix length, then collecting matches is efficient.
Step 3: Compare efficiency and scalability
Trie approach scales better for prefix search due to structured prefix storage and avoids scanning all keys.
Final Answer:
Approach 2 is better because Trie traversal to prefix node is efficient and collects matches quickly -> Option B
Quick Check:
Prefix search = Trie traversal [OK]
Hint: Trie stores prefixes; Hash Map needs full scan for prefix [OK]
Common Mistakes:
Assuming Hash Map prefix checks are fast
Ignoring Trie traversal efficiency
Thinking both approaches perform the same
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.