Skip to content

Commit 028a87b

Browse files
authored
feat: update solutions to lc problem: No.1032 (doocs#949)
No.1032.Stream of Characters
1 parent 9b8e639 commit 028a87b

File tree

4 files changed

+64
-37
lines changed

4 files changed

+64
-37
lines changed

solution/1000-1099/1032.Stream of Characters/README.md

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,16 @@ streamChecker.query("l"); // 返回 True ,因为 'kl' 在 words 中
6262

6363
**方法一:前缀树**
6464

65-
构建前缀树,每个节点保存一个字符,从根节点开始,每次遍历到一个字符,就将其加入到当前节点的子节点中,同时将当前节点的 `isEnd` 标记为 `true`。当遍历到字符串的末尾时,将当前节点的 `isEnd` 标记为 `true`
65+
我们可以根据初始化时的字符串数组 $words$ 构建前缀树,前缀树的每个节点包含两个属性:
6666

67-
查询时,从根节点开始,每次遍历到一个字符,就将其加入到当前节点的子节点中,同时将当前节点的 `isEnd` 标记为 `true`。当遍历到字符串的末尾时,将当前节点的 `isEnd` 标记为 `true`
67+
- `children`:指向 $26$ 个字母的指针数组,用于存储当前节点的子节点。
68+
- `is_end`:标记当前节点是否为某个字符串的结尾。
6869

69-
对于本题,我们采用**字符串的反序**来构建前缀树,这样在查询时,只需要从根节点开始,遍历到当前字符即可,不需要遍历到字符串的末尾
70+
在构造函数中,我们遍历字符串数组 $words$,对于每个字符串 $w$,我们将其反转后,逐个字符插入到前缀树中,插入结束后,将当前节点的 `is_end` 标记为 `true`
7071

71-
初始化前缀树的时间复杂度为 $O(n)$,其中 $n$ 为 `words` 所有字符总数。单次查询的时间复杂度为 $O(m)$,其中 $m$ 为 `words` 中单词的最大长度。
72+
`query` 函数中,我们将当前字符 $c$ 加入到字符流中,然后从后往前遍历字符流,对于每个字符 $c$,我们在前缀树中查找是否存在以 $c$ 为结尾的字符串,如果存在,返回 `true`,否则返回 `false`。注意到 $words$ 中的字符串长度不超过 $200$,因此查询时最多只需要遍历 $200$ 个字符。
73+
74+
时间复杂度方面,构造函数的时间复杂度为 $O(L)$,而 `query` 函数的时间复杂度为 $O(M)$。其中 $L$ 为字符串数组 $words$ 中所有字符串的长度之和,而 $M$ 为字符串数组 $words$ 中字符串的最大长度。空间复杂度 $O(L)$。
7275

7376
<!-- tabs:start -->
7477

@@ -82,7 +85,7 @@ class Trie:
8285
self.children = [None] * 26
8386
self.is_end = False
8487

85-
def insert(self, w):
88+
def insert(self, w: str):
8689
node = self
8790
for c in w[::-1]:
8891
idx = ord(c) - ord('a')
@@ -91,7 +94,7 @@ class Trie:
9194
node = node.children[idx]
9295
node.is_end = True
9396

94-
def search(self, w):
97+
def search(self, w: List[str]) -> bool:
9598
node = self
9699
for c in w[::-1]:
97100
idx = ord(c) - ord('a')
@@ -107,13 +110,14 @@ class StreamChecker:
107110

108111
def __init__(self, words: List[str]):
109112
self.trie = Trie()
110-
self.s = []
113+
self.cs = []
114+
self.limit = 201
111115
for w in words:
112116
self.trie.insert(w)
113117

114118
def query(self, letter: str) -> bool:
115-
self.s.append(letter)
116-
return self.trie.search(self.s[-201:])
119+
self.cs.append(letter)
120+
return self.trie.search(self.cs[-self.limit:])
117121

118122
# Your StreamChecker object will be instantiated and called as such:
119123
# obj = StreamChecker(words)
@@ -190,14 +194,16 @@ public:
190194

191195
Trie()
192196
: children(26)
193-
, isEnd(false) { }
197+
, isEnd(false) {}
194198

195199
void insert(string& w) {
196200
Trie* node = this;
197201
reverse(w.begin(), w.end());
198-
for (char c : w) {
202+
for (char& c : w) {
199203
int idx = c - 'a';
200-
if (!node->children[idx]) node->children[idx] = new Trie();
204+
if (!node->children[idx]) {
205+
node->children[idx] = new Trie();
206+
}
201207
node = node->children[idx];
202208
}
203209
node->isEnd = true;
@@ -207,9 +213,13 @@ public:
207213
Trie* node = this;
208214
for (int i = w.size() - 1, j = 0; ~i && j < 201; --i, ++j) {
209215
int idx = w[i] - 'a';
210-
if (!node->children[idx]) return false;
216+
if (!node->children[idx]) {
217+
return false;
218+
}
211219
node = node->children[idx];
212-
if (node->isEnd) return true;
220+
if (node->isEnd) {
221+
return true;
222+
}
213223
}
214224
return false;
215225
}
@@ -219,8 +229,9 @@ class StreamChecker {
219229
public:
220230
Trie* trie = new Trie();
221231
string s;
232+
222233
StreamChecker(vector<string>& words) {
223-
for (string& w : words) {
234+
for (auto& w : words) {
224235
trie->insert(w);
225236
}
226237
}

solution/1000-1099/1032.Stream of Characters/README_EN.md

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class Trie:
6464
self.children = [None] * 26
6565
self.is_end = False
6666

67-
def insert(self, w):
67+
def insert(self, w: str):
6868
node = self
6969
for c in w[::-1]:
7070
idx = ord(c) - ord('a')
@@ -73,7 +73,7 @@ class Trie:
7373
node = node.children[idx]
7474
node.is_end = True
7575

76-
def search(self, w):
76+
def search(self, w: List[str]) -> bool:
7777
node = self
7878
for c in w[::-1]:
7979
idx = ord(c) - ord('a')
@@ -89,13 +89,14 @@ class StreamChecker:
8989

9090
def __init__(self, words: List[str]):
9191
self.trie = Trie()
92-
self.s = []
92+
self.cs = []
93+
self.limit = 201
9394
for w in words:
9495
self.trie.insert(w)
9596

9697
def query(self, letter: str) -> bool:
97-
self.s.append(letter)
98-
return self.trie.search(self.s[-201:])
98+
self.cs.append(letter)
99+
return self.trie.search(self.cs[-self.limit:])
99100

100101
# Your StreamChecker object will be instantiated and called as such:
101102
# obj = StreamChecker(words)
@@ -170,14 +171,16 @@ public:
170171

171172
Trie()
172173
: children(26)
173-
, isEnd(false) { }
174+
, isEnd(false) {}
174175

175176
void insert(string& w) {
176177
Trie* node = this;
177178
reverse(w.begin(), w.end());
178-
for (char c : w) {
179+
for (char& c : w) {
179180
int idx = c - 'a';
180-
if (!node->children[idx]) node->children[idx] = new Trie();
181+
if (!node->children[idx]) {
182+
node->children[idx] = new Trie();
183+
}
181184
node = node->children[idx];
182185
}
183186
node->isEnd = true;
@@ -187,9 +190,13 @@ public:
187190
Trie* node = this;
188191
for (int i = w.size() - 1, j = 0; ~i && j < 201; --i, ++j) {
189192
int idx = w[i] - 'a';
190-
if (!node->children[idx]) return false;
193+
if (!node->children[idx]) {
194+
return false;
195+
}
191196
node = node->children[idx];
192-
if (node->isEnd) return true;
197+
if (node->isEnd) {
198+
return true;
199+
}
193200
}
194201
return false;
195202
}
@@ -199,8 +206,9 @@ class StreamChecker {
199206
public:
200207
Trie* trie = new Trie();
201208
string s;
209+
202210
StreamChecker(vector<string>& words) {
203-
for (string& w : words) {
211+
for (auto& w : words) {
204212
trie->insert(w);
205213
}
206214
}

solution/1000-1099/1032.Stream of Characters/Solution.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ class Trie {
1010
void insert(string& w) {
1111
Trie* node = this;
1212
reverse(w.begin(), w.end());
13-
for (char c : w) {
13+
for (char& c : w) {
1414
int idx = c - 'a';
15-
if (!node->children[idx]) node->children[idx] = new Trie();
15+
if (!node->children[idx]) {
16+
node->children[idx] = new Trie();
17+
}
1618
node = node->children[idx];
1719
}
1820
node->isEnd = true;
@@ -22,9 +24,13 @@ class Trie {
2224
Trie* node = this;
2325
for (int i = w.size() - 1, j = 0; ~i && j < 201; --i, ++j) {
2426
int idx = w[i] - 'a';
25-
if (!node->children[idx]) return false;
27+
if (!node->children[idx]) {
28+
return false;
29+
}
2630
node = node->children[idx];
27-
if (node->isEnd) return true;
31+
if (node->isEnd) {
32+
return true;
33+
}
2834
}
2935
return false;
3036
}
@@ -34,8 +40,9 @@ class StreamChecker {
3440
public:
3541
Trie* trie = new Trie();
3642
string s;
43+
3744
StreamChecker(vector<string>& words) {
38-
for (string& w : words) {
45+
for (auto& w : words) {
3946
trie->insert(w);
4047
}
4148
}

solution/1000-1099/1032.Stream of Characters/Solution.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ def __init__(self):
33
self.children = [None] * 26
44
self.is_end = False
55

6-
def insert(self, w):
6+
def insert(self, w: str):
77
node = self
88
for c in w[::-1]:
99
idx = ord(c) - ord('a')
@@ -12,7 +12,7 @@ def insert(self, w):
1212
node = node.children[idx]
1313
node.is_end = True
1414

15-
def search(self, w):
15+
def search(self, w: List[str]) -> bool:
1616
node = self
1717
for c in w[::-1]:
1818
idx = ord(c) - ord('a')
@@ -25,16 +25,17 @@ def search(self, w):
2525

2626

2727
class StreamChecker:
28+
2829
def __init__(self, words: List[str]):
2930
self.trie = Trie()
30-
self.s = []
31+
self.cs = []
32+
self.limit = 201
3133
for w in words:
3234
self.trie.insert(w)
3335

3436
def query(self, letter: str) -> bool:
35-
self.s.append(letter)
36-
return self.trie.search(self.s[-201:])
37-
37+
self.cs.append(letter)
38+
return self.trie.search(self.cs[-self.limit:])
3839

3940
# Your StreamChecker object will be instantiated and called as such:
4041
# obj = StreamChecker(words)

0 commit comments

Comments
 (0)