Skip to content

Commit 50b3ab9

Browse files
committed
Add design-add-and-search-words-data-structure solution
1 parent b2a6a85 commit 50b3ab9

File tree

1 file changed

+187
-0
lines changed

1 file changed

+187
-0
lines changed
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/**
2+
* ==================== Complexity Summary ====================
3+
* | Operation | Time Complexity | Space Complexity |
4+
* |------------|------------------------|--------------------|
5+
* | addWord | O(n) | O(n) |
6+
* | search | O(n) (no '.') | O(n) |
7+
* | | O(k^n) (with '.') | O(n) |
8+
* ============================================================
9+
*
10+
* Notes:
11+
* - n: Length of the word being added/searched.
12+
* - k: Average branching factor (number of children per node).
13+
* - Worst-case time complexity for `search` with '.' can grow exponentially
14+
* when many wildcards are present in the word.
15+
*/
16+
17+
var WordDictionary = function () {
18+
this.root = { $: false };
19+
};
20+
21+
/**
22+
* @param {string} word
23+
* @return {void}
24+
*/
25+
WordDictionary.prototype.addWord = function (word) {
26+
let node = this.root;
27+
28+
for (char of word) {
29+
if (!node[char]) {
30+
node[char] = { $: false };
31+
}
32+
node = node[char];
33+
}
34+
35+
node["$"] = true;
36+
};
37+
38+
/**
39+
* @param {string} word
40+
* @return {boolean}
41+
*/
42+
WordDictionary.prototype.search = function (word) {
43+
const dfs = (node, index) => {
44+
// Base case: If we've reached the end of the word
45+
if (index === word.length) {
46+
return node["$"] === true;
47+
}
48+
49+
const char = word[index];
50+
51+
// If the character is not a wildcard
52+
if (char !== ".") {
53+
if (node[char]) {
54+
return dfs(node[char], index + 1); // Continue DFS
55+
} else {
56+
return false; // Character not found
57+
}
58+
}
59+
60+
// If the character is a wildcard
61+
for (const key of Object.keys(node).filter((key) => key !== "$")) {
62+
if (dfs(node[key], index + 1)) {
63+
return true; // Return true if any child path matches
64+
}
65+
// Why we need to check if the recursive call to dfs returns true or false:
66+
// 1) Early termination of recursion when a match is found:
67+
// - Once we find a valid match, there's no need to explore other branches.
68+
// 2) Proper propagation of the result back up the recursion stack:
69+
// - A valid match found in a deeper level of recursion needs to return true
70+
// all the way back to the initial search call to indicate success.
71+
}
72+
73+
return false; // No paths matched for the wildcard
74+
};
75+
76+
return dfs(this.root, 0); // Start DFS from the root node
77+
};
78+
79+
/**
80+
* Your WordDictionary object will be instantiated and called as such:
81+
* var obj = new WordDictionary()
82+
* obj.addWord(word)
83+
* var param_2 = obj.search(word)
84+
*/
85+
86+
// ***** second trial *****
87+
// var WordDictionary = function () {
88+
// this.root = { $: true };
89+
// };
90+
91+
// /**
92+
// * @param {string} word
93+
// * @return {void}
94+
// */
95+
// WordDictionary.prototype.addWord = function (word) {
96+
// const dfs = (node, index) => {
97+
// // exit
98+
// if (index === word.length) {
99+
// node["$"] = true;
100+
// return;
101+
// }
102+
103+
// // add .
104+
// if (!node["."]) {
105+
// node["."] = { $: false };
106+
// }
107+
// dfs(node["."], index + 1);
108+
109+
// // add each character
110+
// const temp = word[index];
111+
112+
// if (!node[temp]) {
113+
// node[temp] = { $: false };
114+
// }
115+
// dfs(node[temp], index + 1);
116+
// };
117+
118+
// dfs(this.root, 0);
119+
// };
120+
121+
// /**
122+
// * @param {string} word
123+
// * @return {boolean}
124+
// */
125+
// WordDictionary.prototype.search = function (word) {
126+
// let node = this.root;
127+
128+
// for (char of word) {
129+
// if (!node[char]) {
130+
// return false;
131+
// }
132+
// node = node[char];
133+
// }
134+
135+
// return node["$"];
136+
// };
137+
138+
/**
139+
* Your WordDictionary object will be instantiated and called as such:
140+
* var obj = new WordDictionary()
141+
* obj.addWord(word)
142+
* var param_2 = obj.search(word)
143+
*/
144+
145+
// ***** first trial *****
146+
// var WordDictionary = function () {
147+
// this.root = new Set();
148+
// };
149+
150+
// /**
151+
// * @param {string} word
152+
// * @return {void}
153+
// */
154+
// WordDictionary.prototype.addWord = function (word) {
155+
// this.root.add(word);
156+
// };
157+
158+
// /**
159+
// * @param {string} word
160+
// * @return {boolean}
161+
// */
162+
// WordDictionary.prototype.search = function (word) {
163+
// if (this.root.size === 0) {
164+
// return false;
165+
// } else {
166+
// for (dict of this.root) {
167+
// if (dict.length === word.length) {
168+
// const found = word
169+
// .split("")
170+
// .every((str, index) => str === "." || dict[index] === str);
171+
// if (found) {
172+
// return true;
173+
// }
174+
// } else {
175+
// continue;
176+
// }
177+
// }
178+
// return false;
179+
// }
180+
// };
181+
182+
/**
183+
* Your WordDictionary object will be instantiated and called as such:
184+
* var obj = new WordDictionary()
185+
* obj.addWord(word)
186+
* var param_2 = obj.search(word)
187+
*/

0 commit comments

Comments
 (0)