Skip to content

Commit 5c890a4

Browse files
Problem 208 (#33)
* add initial solution * add refactored solution and resources * update readme
1 parent 468ba8a commit 5c890a4

File tree

2 files changed

+183
-1
lines changed

2 files changed

+183
-1
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ As I work through this list I figure I would make a GitHub repo with my solution
4343
32. [Clone Graph #133](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/clone-graph-133.md)
4444
33. [Evaluate Reverse Polish Notation #150](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/polish-notation-150.md)
4545
34. [Course Schedule #207](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/course-schedule-207.md)
46-
35. **Implement Trie (Prefix Tree) #208**
46+
35. [Implement Trie (Prefix Tree) #208](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/implement-trie-208.md)
4747
36. Coin Change #322
4848
37. Product of Array Except Self #238
4949
38. Min Stack #155
@@ -151,6 +151,7 @@ In order to practice with similar data structures I'll be placing each problem i
151151
- [3Sum #15](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/3Sum-15.md)
152152
- [Clone Graph #133](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/clone-graph-133.md)
153153
- [LRU Cache #146](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/lru-cache-146.md)
154+
- [Implement Trie (Prefix Tree) #208](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/implement-trie-208.md)
154155

155156
### Binary Tree
156157

@@ -172,6 +173,10 @@ In order to practice with similar data structures I'll be placing each problem i
172173
- [K Closest Points to Origin #973](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/k-closest-origin-973.md)
173174
- [Meeting Rooms II](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/meeting-rooms-ii-253.md)
174175

176+
### Trie
177+
178+
- [Implement Trie (Prefix Tree) #208](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/implement-trie-208.md)
179+
175180
## Algorithm Patterns
176181

177182
Within the problems above there are several patterns that often occur. I plan to categorize each problem such that if you are having problem with a particular pattern you can look for other similar problems that use the same pattern.

medium/implement-trie-208.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# Implement Trie (Prefix Tree)
2+
3+
Page on leetcode: https://leetcode.com/problems/implement-trie-prefix-tree/
4+
5+
## Problem Statement
6+
7+
A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.
8+
9+
Implement the Trie class:
10+
11+
- Trie() Initializes the trie object.
12+
- void insert(String word) Inserts the string word into the trie.
13+
- boolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.
14+
- boolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.
15+
16+
### Constraints
17+
18+
- 1 <= word.length, prefix.length <= 2000
19+
- word and prefix consist only of lowercase English letters.
20+
- At most 3 \* 104 calls in total will be made to insert, search, and startsWith.
21+
22+
### Example
23+
24+
```
25+
Input
26+
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
27+
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
28+
Output
29+
[null, null, true, false, true, null, true]
30+
31+
Explanation
32+
Trie trie = new Trie();
33+
trie.insert("apple");
34+
trie.search("apple"); // return True
35+
trie.search("app"); // return False
36+
trie.startsWith("app"); // return True
37+
trie.insert("app");
38+
trie.search("app"); // return True
39+
```
40+
41+
## Solution
42+
43+
- root node val is empty
44+
- need a Node class?
45+
- Node class has list of next letters
46+
- Need some sort of flag for complete word
47+
- search traverse nodes and if it finds a matching node for each letter and last letter is a complete node will return true
48+
- starts with same as search except complete word not necessary
49+
50+
### Pseudocode
51+
52+
1. Create Node class with val, next letters, complete word
53+
2. Trie creates a node with no val, blank next letters and false complete word
54+
3. Insert takes string and puts into array
55+
4. Loops while array is not empty
56+
5. Checks if node contains letter as nextletter, if not add letter and go to it
57+
6. If array is empty then mark current node as complete word
58+
7. Search takes string and puts into array
59+
8. Loops while array is not empty
60+
9. Checks if node contains letter as nextletter, if not return false
61+
10. If array is empty and current node is a complete word return true, else return false
62+
11. StartsWith takes string and puts into array
63+
12. Loops while array is not empty
64+
13. Checks if node contains letter as nextletter, if not return false
65+
14. If array is empty return true
66+
67+
### Initial Solution
68+
69+
I believe this solution has a time complexity of O(n) for insert and search. Space complexity is O(n) for insertion and O(1) for search.
70+
71+
```javascript
72+
const Node = function (val, completeWord) {
73+
this.val = val;
74+
this.completeWord = completeWord;
75+
this.nextLetters = {};
76+
};
77+
78+
const Trie = function () {
79+
this.root = new Node(null, false);
80+
return null;
81+
};
82+
83+
Trie.prototype.insert = function (word) {
84+
const wordArray = word.split('');
85+
let currChar = this.root;
86+
while (wordArray.length > 0) {
87+
const char = wordArray.shift();
88+
if (char in currChar.nextLetters) {
89+
currChar = currChar.nextLetters[char];
90+
} else {
91+
currChar.nextLetters[char] = new Node(char, false);
92+
currChar = currChar.nextLetters[char];
93+
}
94+
}
95+
currChar.completeWord = true;
96+
return null;
97+
};
98+
99+
Trie.prototype.search = function (word) {
100+
const wordArray = word.split('');
101+
let currChar = this.root;
102+
while (wordArray.length > 0) {
103+
const char = wordArray.shift();
104+
if (char in currChar.nextLetters) {
105+
currChar = currChar.nextLetters[char];
106+
} else {
107+
return false;
108+
}
109+
}
110+
if (currChar.completeWord) {
111+
return true;
112+
}
113+
return false;
114+
};
115+
116+
Trie.prototype.startsWith = function (prefix) {
117+
const wordArray = prefix.split('');
118+
let currChar = this.root;
119+
while (wordArray.length > 0) {
120+
const char = wordArray.shift();
121+
if (char in currChar.nextLetters) {
122+
currChar = currChar.nextLetters[char];
123+
} else {
124+
return false;
125+
}
126+
}
127+
return true;
128+
};
129+
```
130+
131+
### Optimized Solution
132+
133+
The below is roughly the same as above, just with some clean up to make the code more concise. You can see an explanation for this solution here: https://www.youtube.com/watch?v=oobqoCJlHA0
134+
135+
```javascript
136+
const Node = function () {
137+
this.completeWord = false;
138+
this.nextLetters = {};
139+
};
140+
141+
const Trie = function () {
142+
this.root = new Node();
143+
};
144+
145+
Trie.prototype.insert = function (word) {
146+
let cur = this.root;
147+
for (char of word) {
148+
if (!(char in cur.nextLetters)) {
149+
cur.nextLetters[char] = new Node();
150+
}
151+
cur = cur.nextLetters[char];
152+
}
153+
cur.completeWord = true;
154+
};
155+
156+
Trie.prototype.search = function (word) {
157+
let cur = this.root;
158+
for (char of word) {
159+
if (!(char in cur.nextLetters)) {
160+
return false;
161+
}
162+
cur = cur.nextLetters[char];
163+
}
164+
return cur.completeWord;
165+
};
166+
167+
Trie.prototype.startsWith = function (prefix) {
168+
let cur = this.root;
169+
for (char of prefix) {
170+
if (!(char in cur.nextLetters)) {
171+
return false;
172+
}
173+
cur = cur.nextLetters[char];
174+
}
175+
return true;
176+
};
177+
```

0 commit comments

Comments
 (0)