Skip to content

Commit 70c35e4

Browse files
authored
feat: add solutions to lc problems: No.216,247,249 (doocs#2634)
1 parent e04c374 commit 70c35e4

File tree

13 files changed

+237
-140
lines changed

13 files changed

+237
-140
lines changed

solution/0200-0299/0216.Combination Sum III/README.md

+19-21
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,6 @@
7171
- 如果 $i \gt 9$ 或者 $i \gt s$ 或者当前搜索路径 $t$ 的长度大于 $k$,说明当前搜索路径不可能是答案,直接返回。
7272
- 否则,我们可以选择将数字 $i$ 加入搜索路径 $t$ 中,然后继续搜索,即执行 $dfs(i + 1, s - i)$,搜索完成后,将 $i$ 从搜索路径 $t$ 中移除;我们也可以选择不将数字 $i$ 加入搜索路径 $t$ 中,直接执行 $dfs(i + 1, s)$。
7373

74-
方式二:
75-
76-
- 如果 $s = 0$,且当前搜索路径 $t$ 的长度为 $k$,说明找到了一组答案,将 $t$ 加入 $ans$ 中,然后返回。
77-
- 如果 $i \gt 9$ 或者 $i \gt s$ 或者当前搜索路径 $t$ 的长度大于 $k$,说明当前搜索路径不可能是答案,直接返回。
78-
- 否则,我们枚举下一个数字 $j$,即 $j \in [i, 9]$,将数字 $j$ 加入搜索路径 $t$ 中,然后继续搜索,即执行 $dfs(j + 1, s - j)$,搜索完成后,将 $j$ 从搜索路径 $t$ 中移除。
79-
80-
在主函数中,我们调用 $dfs(1, n)$,即从数字 $1$ 开始枚举,剩下和为 $n$ 的数字需要枚举。搜索完成后,即可得到所有的答案。
81-
82-
时间复杂度 $(C_{9}^k \times k)$,空间复杂度 $O(k)$。
83-
8474
<!-- tabs:start -->
8575

8676
```python
@@ -280,19 +270,15 @@ public class Solution {
280270

281271
<!-- tabs:end -->
282272

283-
### 方法二:二进制枚举
284-
285-
我们可以用一个长度为 $9$ 的二进制整数表示数字 $1$ 到 $9$ 的选取情况,其中二进制整数的第 $i$ 位表示数字 $i + 1$ 是否被选取,如果第 $i$ 位为 $1$,则表示数字 $i + 1$ 被选取,否则表示数字 $i + 1$ 没有被选取。
286-
287-
我们在 $[0, 2^9)$ 范围内枚举二进制整数,对于当前枚举到的二进制整数 $mask$,如果 $mask$ 的二进制表示中 $1$ 的个数为 $k$,且 $mask$ 的二进制表示中 $1$ 所对应的数字之和为 $n$,则说明 $mask$ 对应的数字选取方案是一组答案。我们将 $mask$ 对应的数字选取方案加入答案即可。
273+
方式二:
288274

289-
时间复杂度 $O(2^9 \times 9)$,空间复杂度 $O(k)$。
275+
- 如果 $s = 0$,且当前搜索路径 $t$ 的长度为 $k$,说明找到了一组答案,将 $t$ 加入 $ans$ 中,然后返回。
276+
- 如果 $i \gt 9$ 或者 $i \gt s$ 或者当前搜索路径 $t$ 的长度大于 $k$,说明当前搜索路径不可能是答案,直接返回。
277+
- 否则,我们枚举下一个数字 $j$,即 $j \in [i, 9]$,将数字 $j$ 加入搜索路径 $t$ 中,然后继续搜索,即执行 $dfs(j + 1, s - j)$,搜索完成后,将 $j$ 从搜索路径 $t$ 中移除。
290278

291-
相似题目:
279+
在主函数中,我们调用 $dfs(1, n)$,即从数字 $1$ 开始枚举,剩下和为 $n$ 的数字需要枚举。搜索完成后,即可得到所有的答案。
292280

293-
- [39. 组合总和](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0039.Combination%20Sum/README.md)
294-
- [40. 组合总和 II](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0040.Combination%20Sum%20II/README.md)
295-
- [77. 组合](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0077.Combinations/README.md)
281+
时间复杂度 $(C_{9}^k \times k)$,空间复杂度 $O(k)$。
296282

297283
<!-- tabs:start -->
298284

@@ -459,7 +445,19 @@ public class Solution {
459445

460446
<!-- tabs:end -->
461447

462-
### 方法三
448+
### 方法二:二进制枚举
449+
450+
我们可以用一个长度为 $9$ 的二进制整数表示数字 $1$ 到 $9$ 的选取情况,其中二进制整数的第 $i$ 位表示数字 $i + 1$ 是否被选取,如果第 $i$ 位为 $1$,则表示数字 $i + 1$ 被选取,否则表示数字 $i + 1$ 没有被选取。
451+
452+
我们在 $[0, 2^9)$ 范围内枚举二进制整数,对于当前枚举到的二进制整数 $mask$,如果 $mask$ 的二进制表示中 $1$ 的个数为 $k$,且 $mask$ 的二进制表示中 $1$ 所对应的数字之和为 $n$,则说明 $mask$ 对应的数字选取方案是一组答案。我们将 $mask$ 对应的数字选取方案加入答案即可。
453+
454+
时间复杂度 $O(2^9 \times 9)$,空间复杂度 $O(k)$。
455+
456+
相似题目:
457+
458+
- [39. 组合总和](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0039.Combination%20Sum/README.md)
459+
- [40. 组合总和 II](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0040.Combination%20Sum%20II/README.md)
460+
- [77. 组合](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0077.Combinations/README.md)
463461

464462
<!-- tabs:start -->
465463

solution/0200-0299/0216.Combination Sum III/README_EN.md

+33-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,17 @@ Using 4 different numbers in the range [1,9], the smallest sum we can get is 1+2
5656

5757
## Solutions
5858

59-
### Solution 1
59+
### Solution 1: Pruning + Backtracking (Two Approaches)
60+
61+
We design a function $dfs(i, s)$, which represents that we are currently enumerating the number $i$, and there are still numbers with a sum of $s$ to be enumerated. The current search path is $t$, and the answer is $ans$.
62+
63+
The execution logic of the function $dfs(i, s)$ is as follows:
64+
65+
Approach One:
66+
67+
- If $s = 0$ and the length of the current search path $t$ is $k$, it means that a group of answers has been found. Add $t$ to $ans$ and then return.
68+
- If $i \gt 9$ or $i \gt s$ or the length of the current search path $t$ is greater than $k$, it means that the current search path cannot be the answer, so return directly.
69+
- Otherwise, we can choose to add the number $i$ to the search path $t$, and then continue to search, i.e., execute $dfs(i + 1, s - i)$. After the search is completed, remove $i$ from the search path $t$; we can also choose not to add the number $i$ to the search path $t$, and directly execute $dfs(i + 1, s)$.
6070

6171
<!-- tabs:start -->
6272

@@ -257,7 +267,15 @@ public class Solution {
257267

258268
<!-- tabs:end -->
259269

260-
### Solution 2
270+
Another approach:
271+
272+
- If $s = 0$ and the length of the current search path $t$ is $k$, it means that a group of answers has been found. Add $t$ to $ans$ and then return.
273+
- If $i \gt 9$ or $i \gt s$ or the length of the current search path $t$ is greater than $k$, it means that the current search path cannot be the answer, so return directly.
274+
- Otherwise, we enumerate the next number $j$, i.e., $j \in [i, 9]$, add the number $j$ to the search path $t$, and then continue to search, i.e., execute $dfs(j + 1, s - j)$. After the search is completed, remove $j$ from the search path $t$.
275+
276+
In the main function, we call $dfs(1, n)$, i.e., start enumerating from the number $1$, and the remaining numbers with a sum of $n$ need to be enumerated. After the search is completed, we can get all the answers.
277+
278+
The time complexity is $(C_{9}^k \times k)$, and the space complexity is $O(k)$.
261279

262280
<!-- tabs:start -->
263281

@@ -424,7 +442,19 @@ public class Solution {
424442

425443
<!-- tabs:end -->
426444

427-
### Solution 3
445+
### Solution 2: Binary Enumeration
446+
447+
We can use a binary integer of length $9$ to represent the selection of numbers $1$ to $9$, where the $i$-th bit of the binary integer represents whether the number $i + 1$ is selected. If the $i$-th bit is $1$, it means that the number $i + 1$ is selected, otherwise, it means that the number $i + 1$ is not selected.
448+
449+
We enumerate binary integers in the range of $[0, 2^9)$. For the currently enumerated binary integer $mask$, if the number of $1$s in the binary representation of $mask$ is $k$, and the sum of the numbers corresponding to $1$ in the binary representation of $mask$ is $n$, it means that the number selection scheme corresponding to $mask$ is a group of answers. We can add the number selection scheme corresponding to $mask$ to the answer.
450+
451+
The time complexity is $O(2^9 \times 9)$, and the space complexity is $O(k)$.
452+
453+
Similar problems:
454+
455+
- [39. Combination Sum](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0039.Combination%20Sum/README_EN.md)
456+
- [40. Combination Sum II](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0040.Combination%20Sum%20II/README_EN.md)
457+
- [77. Combinations](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0077.Combinations/README_EN.md)
428458

429459
<!-- tabs:start -->
430460

solution/0200-0299/0246.Strobogrammatic Number/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242

4343
我们定义一个数组 $d$,其中 $d[i]$ 表示数字 $i$ 旋转 180° 之后的数字。如果 $d[i]$ 为 $-1$,表示数字 $i$ 不能旋转 180° 得到一个数字。
4444

45-
定义两个指针 $i$ 和 $j$,分别指向字符串的左右两端,然后不断向中间移动指针,判断 $d[num[i]]$ 和 $num[j]$ 是否相等,如果不相等,说明该字符串不是中心对称数 🔒,直接返回 $false$ 即可。如果 $i \gt j$,说明遍历完了字符串,返回 $true$。
45+
定义两个指针 $i$ 和 $j$,分别指向字符串的左右两端,然后不断向中间移动指针,判断 $d[num[i]]$ 和 $num[j]$ 是否相等,如果不相等,说明该字符串不是中心对称数,直接返回 $false$ 即可。如果 $i \gt j$,说明遍历完了字符串,返回 $true$。
4646

47-
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为字符串的长度
47+
时间复杂度 $O(n)$,其中 $n$ 为字符串的长度。空间复杂度 $O(1)$。
4848

4949
<!-- tabs:start -->
5050

solution/0200-0299/0246.Strobogrammatic Number/README_EN.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@
4343

4444
## Solutions
4545

46-
### Solution 1
46+
### Solution 1: Two Pointers Simulation
47+
48+
We define an array $d$, where $d[i]$ represents the number after rotating the digit $i$ by 180°. If $d[i]$ is $-1$, it means that the digit $i$ cannot be rotated 180° to get a valid digit.
49+
50+
We define two pointers $i$ and $j$, pointing to the left and right ends of the string, respectively. Then we continuously move the pointers towards the center, checking whether $d[num[i]]$ and $num[j]$ are equal. If they are not equal, it means that the string is not a strobogrammatic number, and we can directly return $false$. If $i > j$, it means that we have traversed the entire string, and we return $true$.
51+
52+
The time complexity is $O(n)$, where $n$ is the length of the string. The space complexity is $O(1)$.
4753

4854
<!-- tabs:start -->
4955

solution/0200-0299/0247.Strobogrammatic Number II/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555

5656
相似题目:
5757

58-
- [248. 中心对称数 II 🔒I](https://github.com/doocs/leetcode/blob/main/solution/0200-0299/0248.Strobogrammatic%20Number%20III/README.md)
58+
- [248. 中心对称数 III 🔒](https://github.com/doocs/leetcode/blob/main/solution/0200-0299/0248.Strobogrammatic%20Number%20III/README.md)
5959

6060
<!-- tabs:start -->
6161

solution/0200-0299/0247.Strobogrammatic Number II/README_EN.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,25 @@
2727

2828
## Solutions
2929

30-
### Solution 1
30+
### Solution 1: Recursion
31+
32+
If the length is $1$, then the strobogrammatic numbers are only $0, 1, 8$; if the length is $2$, then the strobogrammatic numbers are only $11, 69, 88, 96$.
33+
34+
We design a recursive function $dfs(u)$, which returns the strobogrammatic numbers of length $u$. The answer is $dfs(n)$.
35+
36+
If $u$ is $0$, return a list containing an empty string, i.e., `[""]`; if $u$ is $1$, return the list `["0", "1", "8"]`.
37+
38+
If $u$ is greater than $1$, we traverse all the strobogrammatic numbers of length $u - 2$. For each strobogrammatic number $v$, we add $1, 8, 6, 9$ to both sides of it, and we can get the strobogrammatic numbers of length `u`.
39+
40+
Note that if $u \neq n$, we can also add $0$ to both sides of the strobogrammatic number.
41+
42+
Finally, we return all the strobogrammatic numbers of length $n$.
43+
44+
The time complexity is $O(2^{n+2})$.
45+
46+
Similar problems:
47+
48+
- [248. Strobogrammatic Number III 🔒](https://github.com/doocs/leetcode/blob/main/solution/0200-0299/0248.Strobogrammatic%20Number%20III/README_EN.md)
3149

3250
<!-- tabs:start -->
3351

solution/0200-0299/0248.Strobogrammatic Number III/README_EN.md

+21-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,27 @@
3030

3131
## Solutions
3232

33-
### Solution 1
33+
### Solution 1: Recursion
34+
35+
If the length is $1$, then the strobogrammatic numbers are only $0, 1, 8$; if the length is $2$, then the strobogrammatic numbers are only $11, 69, 88, 96$.
36+
37+
We design a recursive function $dfs(u)$, which returns the strobogrammatic numbers of length $u$.
38+
39+
If $u$ is $0$, return a list containing an empty string, i.e., `[""]`; if $u$ is $1$, return the list `["0", "1", "8"]`.
40+
41+
If $u$ is greater than $1$, we traverse all the strobogrammatic numbers of length $u - 2$. For each strobogrammatic number $v$, we add $1, 8, 6, 9$ to both sides of it, and we can get the strobogrammatic numbers of length $u$.
42+
43+
Note that if $u \neq n$, we can also add $0$ to both sides of the strobogrammatic number.
44+
45+
Let the lengths of $low$ and $high$ be $a$ and $b$ respectively.
46+
47+
Next, we traverse all lengths in the range $[a,..b]$. For each length $n$, we get all strobogrammatic numbers $dfs(n)$, and then check whether they are in the range $[low, high]$. If they are, we increment the answer.
48+
49+
The time complexity is $O(2^{n+2} \times \log n)$.
50+
51+
Similar problems:
52+
53+
- [247. Strobogrammatic Number II](https://github.com/doocs/leetcode/blob/main/solution/0200-0299/0247.Strobogrammatic%20Number%20II/README_EN.md)
3454

3555
<!-- tabs:start -->
3656

solution/0200-0299/0249.Group Shifted Strings/README.md

+48-37
Original file line numberDiff line numberDiff line change
@@ -30,45 +30,50 @@
3030

3131
## 解法
3232

33-
### 方法一
33+
### 方法一:哈希表
34+
35+
我们用一个哈希表 $g$ 来存储每个字符串移位后且首位为 '`a`' 的字符串。即 $g[t]$ 表示所有字符串移位后字符串为 $t$ 的字符串集合。
36+
37+
我们遍历每个字符串,对于每个字符串,我们计算其移位后的字符串 $t$,然后将其加入到 $g[t]$ 中。
38+
39+
最后,我们将 $g$ 中的所有值取出来,即为答案。
40+
41+
时间复杂度 $O(L)$,空间复杂度 $O(L)$,其中 $L$ 为所有字符串的长度之和。
3442

3543
<!-- tabs:start -->
3644

3745
```python
3846
class Solution:
3947
def groupStrings(self, strings: List[str]) -> List[List[str]]:
40-
mp = defaultdict(list)
48+
g = defaultdict(list)
4149
for s in strings:
50+
diff = ord(s[0]) - ord("a")
4251
t = []
43-
diff = ord(s[0]) - ord('a')
4452
for c in s:
45-
d = ord(c) - diff
46-
if d < ord('a'):
47-
d += 26
48-
t.append(chr(d))
49-
k = ''.join(t)
50-
mp[k].append(s)
51-
return list(mp.values())
53+
c = ord(c) - diff
54+
if c < ord("a"):
55+
c += 26
56+
t.append(chr(c))
57+
g["".join(t)].append(s)
58+
return list(g.values())
5259
```
5360

5461
```java
5562
class Solution {
5663
public List<List<String>> groupStrings(String[] strings) {
57-
Map<String, List<String>> mp = new HashMap<>();
58-
for (String s : strings) {
59-
int diff = s.charAt(0) - 'a';
64+
Map<String, List<String>> g = new HashMap<>();
65+
for (var s : strings) {
6066
char[] t = s.toCharArray();
67+
int diff = t[0] - 'a';
6168
for (int i = 0; i < t.length; ++i) {
62-
char d = (char) (t[i] - diff);
63-
if (d < 'a') {
64-
d += 26;
69+
t[i] = (char) (t[i] - diff);
70+
if (t[i] < 'a') {
71+
t[i] += 26;
6572
}
66-
t[i] = d;
6773
}
68-
String key = new String(t);
69-
mp.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
74+
g.computeIfAbsent(new String(t), k -> new ArrayList<>()).add(s);
7075
}
71-
return new ArrayList<>(mp.values());
76+
return new ArrayList<>(g.values());
7277
}
7378
}
7479
```
@@ -77,38 +82,44 @@ class Solution {
7782
class Solution {
7883
public:
7984
vector<vector<string>> groupStrings(vector<string>& strings) {
80-
unordered_map<string, vector<string>> mp;
85+
unordered_map<string, vector<string>> g;
8186
for (auto& s : strings) {
87+
string t;
8288
int diff = s[0] - 'a';
83-
string t = s;
84-
for (int i = 0; i < t.size(); ++i) {
85-
char d = t[i] - diff;
86-
if (d < 'a') d += 26;
87-
t[i] = d;
89+
for (int i = 0; i < s.size(); ++i) {
90+
char c = s[i] - diff;
91+
if (c < 'a') {
92+
c += 26;
93+
}
94+
t.push_back(c);
8895
}
89-
cout << t << endl;
90-
mp[t].push_back(s);
96+
g[t].emplace_back(s);
9197
}
9298
vector<vector<string>> ans;
93-
for (auto& e : mp)
94-
ans.push_back(e.second);
99+
for (auto& p : g) {
100+
ans.emplace_back(move(p.second));
101+
}
95102
return ans;
96103
}
97104
};
98105
```
99106
100107
```go
101108
func groupStrings(strings []string) [][]string {
102-
mp := make(map[string][]string)
109+
g := make(map[string][]string)
103110
for _, s := range strings {
104-
k := ""
105-
for i := range s {
106-
k += string((s[i]-s[0]+26)%26 + 'a')
111+
t := []byte(s)
112+
diff := t[0] - 'a'
113+
for i := range t {
114+
t[i] -= diff
115+
if t[i] < 'a' {
116+
t[i] += 26
117+
}
107118
}
108-
mp[k] = append(mp[k], s)
119+
g[string(t)] = append(g[string(t)], s)
109120
}
110-
var ans [][]string
111-
for _, v := range mp {
121+
ans := make([][]string, 0, len(g))
122+
for _, v := range g {
112123
ans = append(ans, v)
113124
}
114125
return ans

0 commit comments

Comments
 (0)