Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5d280e6

Browse files
Merge pull request #789 from SharingSource/ac_oier
🌟 feat: add 1032、1129、139、1441、1620、1652、1691、1697、1760、1780、1879、654...
2 parents 9296bfe + 64a6496 commit 5d280e6

File tree

30 files changed

+1807
-463
lines changed

30 files changed

+1807
-463
lines changed

‎LeetCode/1031-1040/1032. 字符流(困难).md‎

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ streamChecker.query("l"); // 返回 True ,因为 'kl' 在 words 中
6161

6262
> 一些细节:为了避免每个样例都 `new` 大数组,我们可以使用 `static` 优化。
6363
64-
代码:
64+
Java 代码:
6565
```Java
6666
class StreamChecker {
6767
static int N = 2010 * 200, idx = 0;
@@ -104,6 +104,48 @@ class StreamChecker {
104104
}
105105
}
106106
```
107+
C++ 代码:
108+
```C++
109+
class StreamChecker {
110+
public:
111+
static const int N = 2010 * 200;
112+
int tr[N][26];
113+
bool isEnd[N];
114+
string sb;
115+
int idx = 0;
116+
void add(const string &s) {
117+
int p = 0;
118+
for (char c : s) {
119+
int u = c - 'a';
120+
if (tr[p][u] == 0) tr[p][u] = ++idx;
121+
p = tr[p][u];
122+
}
123+
isEnd[p] = true;
124+
}
125+
bool query(int start, int end) {
126+
int p = 0;
127+
for (int i = start; i <= end; i++) {
128+
int u = sb[i] - 'a';
129+
if (tr[p][u] == 0) return false;
130+
p = tr[p][u];
131+
}
132+
return isEnd[p];
133+
}
134+
StreamChecker(const vector<string>& words) {
135+
memset(tr, 0, sizeof(tr));
136+
memset(isEnd, 0, sizeof(isEnd));
137+
for (const string &s : words) add(s);
138+
}
139+
bool query(char c) {
140+
sb.push_back(c);
141+
int n = sb.length(), min = max(0, n - 200);
142+
for (int i = n - 1; i >= min; i--) {
143+
if (query(i, n - 1)) return true;
144+
}
145+
return false;
146+
}
147+
};
148+
```
107149
* 时间复杂度:`StreamChecker` 初始化复杂度为 $O(n),ドル其中 $n$ 为 `words` 字符总数;`query` 操作复杂度为 $O(m^2),ドル其中 $m = 200$ 为最大 `words[i]` 长度
108150
* 空间复杂度:$O(n \times C),ドル其中 $n$ 为 `words` 字符总数,$C = 26$ 为字符集大小
109151
@@ -123,7 +165,7 @@ class StreamChecker {
123165
124166
同理,我们可以利用最大的 `words[i]` 长度为 200ドル$ 来控制从 $s[n - 1]$ 开始往回找的最远距离,同时利用当某个短后缀不在 `Trie` 中,则其余长度更大的后缀必然不在 `Trie` 中进行剪枝操作。
125167
126-
代码:
168+
Java 代码:
127169
```Java
128170
class StreamChecker {
129171
static int N = 2010 * 200, idx = 0;
@@ -160,6 +202,47 @@ class StreamChecker {
160202
}
161203
}
162204
```
205+
C++ 代码:
206+
```C++
207+
class StreamChecker {
208+
public:
209+
static const int N = 2010 * 200;
210+
static const int ALPHABET_SIZE = 26;
211+
vector<vector<int>> tr;
212+
vector<bool> isEnd;
213+
string sb;
214+
int idx = 0;
215+
void add(const string &s) {
216+
int p = 0;
217+
for (int i = s.length() - 1; i >= 0; i--) {
218+
int u = s[i] - 'a';
219+
if (tr[p].size() <= u) tr[p].resize(u + 1, 0);
220+
if (tr[p][u] == 0) tr[p][u] = ++idx;
221+
p = tr[p][u];
222+
}
223+
isEnd[p] = true;
224+
}
225+
StreamChecker(const vector<string>& words) {
226+
tr.resize(N);
227+
isEnd.resize(N);
228+
fill(isEnd.begin(), isEnd.end(), false);
229+
for (const auto &s : words) {
230+
add(s);
231+
}
232+
}
233+
bool query(char c) {
234+
sb.push_back(c);
235+
int n = sb.length(), min = max(0, n - 200), p = 0;
236+
for (int i = n - 1; i >= min; i--) {
237+
if (isEnd[p]) return true;
238+
int u = sb[i] - 'a';
239+
if (tr[p].size() <= u || tr[p][u] == 0) return false;
240+
p = tr[p][u];
241+
}
242+
return isEnd[p];
243+
}
244+
};
245+
```
163246
* 时间复杂度:`StreamChecker` 初始化复杂度为 $O(n),ドル其中 $n$ 为 `words` 字符总数;`query` 操作复杂度为 $O(m),ドル其中 $m = 200$ 为最大 `words[i]` 长度
164247
* 空间复杂度:$O(n \times C),ドル其中 $n$ 为 `words` 字符总数,$C = 26$ 为字符集大小
165248

‎LeetCode/1221-1230/1129. 颜色交替的最短路径(中等).md‎

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@ Tag : 「BFS」、「最短路」
66

77

88

9-
在一个有向图中,节点分别标记为 `0, 1, ..., n-1`图中每条边为红色或者蓝色,且存在自环或平行边。
9+
在一个有向图中,节点分别标记为 `0, 1, ..., n-1`
1010

11-
`red_edges` 中的每一个 `[i, j]` 对表示从节点 `i` 到节点 `j` 的红色有向边。类似地,`blue_edges` 中的每一个 `[i, j]` 对表示从节点 `i` 到节点 `j` 的蓝色有向边
11+
图中每条边为红色或者蓝色,且存在自环或平行边
1212

13-
返回长度为 `n` 的数组 `answer`,其中 `answer[X]` 是从节点 `0` 到节点 `X` 的红色边和蓝色边交替出现的最短路径的长度。如果不存在这样的路径,那么 `answer[x] = -1`
13+
`red_edges` 中的每一个 `[i, j]` 对表示从节点 `i` 到节点 `j` 的红色有向边。
14+
15+
类似地,`blue_edges` 中的每一个 `[i, j]` 对表示从节点 `i` 到节点 `j` 的蓝色有向边。
16+
17+
返回长度为 `n` 的数组 `answer`,其中 `answer[X]` 是从节点 `0` 到节点 `X` 的红色边和蓝色边交替出现的最短路径的长度。
18+
19+
如果不存在这样的路径,那么 `answer[x] = -1`
1420

1521
示例 1:
1622
```
@@ -70,7 +76,7 @@ Tag : 「BFS」、「最短路」
7076

7177
利用数据范围不大(点数为 100ドル,ドル边数为 800ドル$),可以直接对每个点进行一次独立的 `BFS` 来求最短路。由于图存在重边和自环,因此在求解最短路的过程需要对边进行去重。
7278

73-
代码:
79+
Java 代码:
7480
```Java
7581
class Solution {
7682
static int N = 110, M = 810, idx = 0;
@@ -115,6 +121,54 @@ class Solution {
115121
}
116122
}
117123
```
124+
C++ 代码:
125+
```C++
126+
class Solution {
127+
public:
128+
int he[110], e[810], ne[810], w[810], idx = 0;
129+
void add(int a, int b, int c) {
130+
e[idx] = b;
131+
w[idx] = c;
132+
ne[idx] = he[a];
133+
he[a] = idx++;
134+
}
135+
vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& rs, vector<vector<int>>& bs) {
136+
idx = 0;
137+
fill(he, he + n, -1);
138+
for (auto& e : rs) add(e[0], e[1], 1);
139+
for (auto& e : bs) add(e[0], e[1], -1);
140+
vector<int> ans(n);
141+
vector<bool> vis(rs.size() + bs.size());
142+
for (int k = 1; k < n; k++) {
143+
ans[k] = -1;
144+
fill(vis.begin(), vis.end(), false);
145+
queue<vector<int>> q;
146+
q.push({ 0, 0, 0 }); // point, last, step
147+
bool out = false;
148+
while (!q.empty()) {
149+
if (out) break;
150+
vector<int> info = q.front(); q.pop();
151+
int p = info[0], last = info[1], step = info[2];
152+
for (int i = he[p]; i != -1; i = ne[i]) {
153+
int j = e[i], c = w[i];
154+
if (vis[i]) continue;
155+
if (c + last == 0 || last == 0) {
156+
if (j == k) {
157+
ans[k] = step + 1;
158+
out = true;
159+
break;
160+
} else {
161+
q.push({ j, c, step + 1 });
162+
vis[i] = true;
163+
}
164+
}
165+
}
166+
}
167+
}
168+
return ans;
169+
}
170+
};
171+
```
118172
* 时间复杂度:将点数记为 `n` ,边数记为 `m`。建图复杂度为 $O(m)$;构造答案复杂度为 $O(n \times (n + m))$。整体复杂度为 $O(n \times (n + m))$
119173
* 空间复杂度:$O(n + m)$
120174
@@ -128,7 +182,7 @@ class Solution {
128182
129183
因此我们只需要初始化所有的 `ans[i] = -1`,并从节点 `0` 开始进行一次 `BFS` 即可。
130184
131-
代码:
185+
Java 代码:
132186
```Java
133187
class Solution {
134188
static int N = 110, M = 810, idx = 0;
@@ -168,14 +222,53 @@ class Solution {
168222
}
169223
}
170224
```
225+
C++ 代码:
226+
```C++
227+
class Solution {
228+
public:
229+
int he[110], e[810], ne[810], w[810], idx = 0;
230+
void add(int a, int b, int c) {
231+
e[idx] = b;
232+
w[idx] = c;
233+
ne[idx] = he[a];
234+
he[a] = idx++;
235+
}
236+
vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& rs, vector<vector<int>>& bs) {
237+
idx = 0;
238+
fill(he, he + n, -1);
239+
for (auto& e : rs) add(e[0], e[1], 1);
240+
for (auto& e : bs) add(e[0], e[1], -1);
241+
vector<int> ans(n, -1);
242+
ans[0] = 0;
243+
vector<bool> vis(rs.size() + bs.size(), false);
244+
deque<vector<int>> d;
245+
d.push_back({0, 0, 0}); // point, last, step
246+
while (!d.empty()) {
247+
vector<int> info = d.front();
248+
d.pop_front();
249+
int p = info[0], last = info[1], step = info[2];
250+
for (int i = he[p]; i != -1; i = ne[i]) {
251+
if (vis[i]) continue;
252+
int j = e[i], c = w[i];
253+
if (c + last == 0 || last == 0) {
254+
ans[j] = ans[j] == -1 ? step + 1 : min(ans[j], step + 1);
255+
d.push_back({j, c, step + 1});
256+
vis[i] = true;
257+
}
258+
}
259+
}
260+
return ans;
261+
}
262+
};
263+
```
171264
* 时间复杂度:将点数记为 `n` ,边数记为 `m`。建图复杂度为 $O(m)$;构造答案复杂度为 $O(n + m)$。整体复杂度为 $O(n + m)$
172265
* 空间复杂度:$O(n + m)$
173266
174267
---
175268
176269
### 最后
177270
178-
这是我们「刷穿 LeetCode」系列文章的第 `No.1224` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
271+
这是我们「刷穿 LeetCode」系列文章的第 `No.1129` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
179272
180273
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
181274

‎LeetCode/131-140/139. 单词拆分(中等).md‎

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,27 @@ class Solution {
7474
}
7575
}
7676
```
77-
TypeScript 代码:
78-
```TypeScript
79-
function wordBreak(s: string, wordDict: string[]): boolean {
80-
const ss = new Set<string>(wordDict)
81-
const n = s.length
82-
const f = new Array<boolean>(n + 10).fill(false)
83-
f[0] = true
84-
for (let i = 1; i <= n; i++) {
85-
for (let j = i; j >= 1 && !f[i]; j--) {
86-
const sub = s.substring(j - 1, i)
87-
if (ss.has(sub)) f[i] = f[j - 1]
77+
C++ 代码:
78+
```C++
79+
class Solution {
80+
public:
81+
bool wordBreak(string s, vector<string>& wordDict) {
82+
unordered_set<string> set;
83+
for (const string& word : wordDict) {
84+
set.insert(word);
8885
}
86+
int n = s.length();
87+
vector<bool> f(n + 10, false);
88+
f[0] = true;
89+
for (int i = 1; i <= n; ++i) {
90+
for (int j = 1; j <= i && !f[i]; ++j) {
91+
string sub = s.substr(j - 1, i - j + 1);
92+
if (set.find(sub) != set.end()) f[i] = f[j - 1] || f[i];
93+
}
94+
}
95+
return f[n];
8996
}
90-
return f[n]
91-
}
97+
};
9298
```
9399
Python 代码:
94100
```Python
@@ -107,6 +113,22 @@ class Solution:
107113
j -= 1
108114
return f[n]
109115
```
116+
TypeScript 代码:
117+
```TypeScript
118+
function wordBreak(s: string, wordDict: string[]): boolean {
119+
const ss = new Set<string>(wordDict)
120+
const n = s.length
121+
const f = new Array<boolean>(n + 10).fill(false)
122+
f[0] = true
123+
for (let i = 1; i <= n; i++) {
124+
for (let j = i; j >= 1 && !f[i]; j--) {
125+
const sub = s.substring(j - 1, i)
126+
if (ss.has(sub)) f[i] = f[j - 1]
127+
}
128+
}
129+
return f[n]
130+
}
131+
```
110132
* 时间复杂度:将 `wordDict` 转存在 `Set` 复杂度为 $O(m)$;`DP` 过程复忽裁剪子串和查询 `Set` 结构的常数,复杂度为 $O(n^2)$
111133
* 空间复杂度:$O(n + m)$
112134

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /