Skip to content

Commit ac26e1a

Browse files
authored
feat: update solutions to lc problems: No.39~42 (#2469)
1 parent 661ab46 commit ac26e1a

File tree

11 files changed

+103
-183
lines changed

11 files changed

+103
-183
lines changed

solution/0000-0099/0039.Combination Sum/README.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,14 @@
5252

5353
## 解法
5454

55-
### 方法一:排序 + 剪枝 + 回溯(两种写法)
55+
### 方法一:排序 + 剪枝 + 回溯
5656

5757
我们可以先对数组进行排序,方便剪枝。
5858

5959
接下来,我们设计一个函数 $dfs(i, s)$,表示从下标 $i$ 开始搜索,且剩余目标值为 $s$,其中 $i$ 和 $s$ 都是非负整数,当前搜索路径为 $t$,答案为 $ans$。
6060

6161
在函数 $dfs(i, s)$ 中,我们先判断 $s$ 是否为 $0$,如果是,则将当前搜索路径 $t$ 加入答案 $ans$ 中,然后返回。如果 $s \lt candidates[i]$,说明当前下标及后面的下标的元素都大于剩余目标值 $s$,路径不合法,直接返回。否则,我们从下标 $i$ 开始搜索,搜索的下标范围是 $j \in [i, n)$,其中 $n$ 为数组 $candidates$ 的长度。在搜索的过程中,我们将当前下标的元素加入搜索路径 $t$,递归调用函数 $dfs(j, s - candidates[j])$,递归结束后,将当前下标的元素从搜索路径 $t$ 中移除。
6262

63-
我们也可以将函数 $dfs(i, s)$ 的实现逻辑改为另一种写法。在函数 $dfs(i, s)$ 中,我们先判断 $s$ 是否为 $0$,如果是,则将当前搜索路径 $t$ 加入答案 $ans$ 中,然后返回。如果 $i \geq n$ 或者 $s \lt candidates[i]$,路径不合法,直接返回。否则,我们考虑两种情况,一种是不选当前下标的元素,即递归调用函数 $dfs(i + 1, s)$,另一种是选当前下标的元素,即递归调用函数 $dfs(i, s - candidates[i])$。
64-
6563
在主函数中,我们只要调用函数 $dfs(0, target)$,即可得到答案。
6664

6765
时间复杂度 $O(2^n \times n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $candidates$ 的长度。由于剪枝,实际的时间复杂度要远小于 $O(2^n \times n)$。
@@ -258,7 +256,11 @@ public class Solution {
258256

259257
<!-- tabs:end -->
260258

261-
### 方法二
259+
### 方法二:排序 + 剪枝 + 回溯(写法二)
260+
261+
我们也可以将函数 $dfs(i, s)$ 的实现逻辑改为另一种写法。在函数 $dfs(i, s)$ 中,我们先判断 $s$ 是否为 $0$,如果是,则将当前搜索路径 $t$ 加入答案 $ans$ 中,然后返回。如果 $i \geq n$ 或者 $s \lt candidates[i]$,路径不合法,直接返回。否则,我们考虑两种情况,一种是不选当前下标的元素,即递归调用函数 $dfs(i + 1, s)$,另一种是选当前下标的元素,即递归调用函数 $dfs(i, s - candidates[i])$。
262+
263+
时间复杂度 $O(2^n \times n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $candidates$ 的长度。由于剪枝,实际的时间复杂度要远小于 $O(2^n \times n)$。
262264

263265
<!-- tabs:start -->
264266

solution/0000-0099/0039.Combination Sum/README_EN.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,14 @@ These are the only two combinations.
5050

5151
## Solutions
5252

53-
### Solution 1: Sorting + Pruning + Backtracking (Two Implementations)
53+
### Solution 1: Sorting + Pruning + Backtracking
5454

5555
We can first sort the array to facilitate pruning.
5656

5757
Next, we design a function $dfs(i, s)$, which means starting the search from index $i$ with a remaining target value of $s$. Here, $i$ and $s$ are both non-negative integers, the current search path is $t$, and the answer is $ans$.
5858

5959
In the function $dfs(i, s)$, we first check whether $s$ is $0$. If it is, we add the current search path $t$ to the answer $ans$, and then return. If $s \lt candidates[i]$, it means that the elements of the current index and the following indices are all greater than the remaining target value $s$, and the path is invalid, so we return directly. Otherwise, we start the search from index $i$, and the search index range is $j \in [i, n)$, where $n$ is the length of the array $candidates$. During the search, we add the element of the current index to the search path $t$, recursively call the function $dfs(j, s - candidates[j])$, and after the recursion ends, we remove the element of the current index from the search path $t$.
6060

61-
We can also change the implementation logic of the function $dfs(i, s)$ to another form. In the function $dfs(i, s)$, we first check whether $s$ is $0$. If it is, we add the current search path $t$ to the answer $ans$, and then return. If $i \geq n$ or $s \lt candidates[i]$, the path is invalid, so we return directly. Otherwise, we consider two situations, one is not selecting the element of the current index, that is, recursively calling the function $dfs(i + 1, s)$, and the other is selecting the element of the current index, that is, recursively calling the function $dfs(i, s - candidates[i])$.
62-
6361
In the main function, we just need to call the function $dfs(0, target)$ to get the answer.
6462

6563
The time complexity is $O(2^n \times n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $candidates$. Due to pruning, the actual time complexity is much less than $O(2^n \times n)$.
@@ -256,7 +254,11 @@ public class Solution {
256254

257255
<!-- tabs:end -->
258256

259-
### Solution 2
257+
### Solution 2: Sorting + Pruning + Backtracking(Another Form)
258+
259+
We can also change the implementation logic of the function $dfs(i, s)$ to another form. In the function $dfs(i, s)$, we first check whether $s$ is $0$. If it is, we add the current search path $t$ to the answer $ans$, and then return. If $i \geq n$ or $s \lt candidates[i]$, the path is invalid, so we return directly. Otherwise, we consider two situations, one is not selecting the element of the current index, that is, recursively calling the function $dfs(i + 1, s)$, and the other is selecting the element of the current index, that is, recursively calling the function $dfs(i, s - candidates[i])$.
260+
261+
The time complexity is $O(2^n \times n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $candidates$. Due to pruning, the actual time complexity is much less than $O(2^n \times n)$.
260262

261263
<!-- tabs:start -->
262264

solution/0000-0099/0040.Combination Sum II/README.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,14 @@
5050

5151
## 解法
5252

53-
### 方法一:排序 + 剪枝 + 回溯(两种写法)
53+
### 方法一:排序 + 剪枝 + 回溯
5454

5555
我们可以先对数组进行排序,方便剪枝以及跳过重复的数字。
5656

5757
接下来,我们设计一个函数 $dfs(i, s)$,表示从下标 $i$ 开始搜索,且剩余目标值为 $s$,其中 $i$ 和 $s$ 都是非负整数,当前搜索路径为 $t$,答案为 $ans$。
5858

5959
在函数 $dfs(i, s)$ 中,我们先判断 $s$ 是否为 $0$,如果是,则将当前搜索路径 $t$ 加入答案 $ans$ 中,然后返回。如果 $i \geq n$,或者 $s \lt candidates[i]$,说明当前路径不合法,直接返回。否则,我们从下标 $i$ 开始搜索,搜索的下标范围是 $j \in [i, n)$,其中 $n$ 为数组 $candidates$ 的长度。在搜索的过程中,如果 $j \gt i$ 并且 $candidates[j] = candidates[j - 1]$,说明当前数字与上一个数字相同,我们可以跳过当前数字,因为上一个数字已经搜索过了。否则,我们将当前数字加入搜索路径 $t$ 中,然后递归调用函数 $dfs(j + 1, s - candidates[j])$,然后将当前数字从搜索路径 $t$ 中移除。
6060

61-
我们也可以将函数 $dfs(i, s)$ 的实现逻辑改为另一种写法。如果我们选择当前数字,那么我们将当前数字加入搜索路径 $t$ 中,然后递归调用函数 $dfs(i + 1, s - candidates[i])$,然后将当前数字从搜索路径 $t$ 中移除。如果我们不选择当前数字,那么我们可以跳过与当前数字相同的所有数字,然后递归调用函数 $dfs(j, s)$,其中 $j$ 为第一个与当前数字不同的数字的下标。
62-
6361
在主函数中,我们只要调用函数 $dfs(0, target)$,即可得到答案。
6462

6563
时间复杂度 $O(2^n \times n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $candidates$ 的长度。由于剪枝,实际的时间复杂度要远小于 $O(2^n \times n)$。
@@ -310,7 +308,11 @@ public class Solution {
310308

311309
<!-- tabs:end -->
312310

313-
### 方法二
311+
### 方法二:排序 + 剪枝 + 回溯(写法二)
312+
313+
我们也可以将函数 $dfs(i, s)$ 的实现逻辑改为另一种写法。如果我们选择当前数字,那么我们将当前数字加入搜索路径 $t$ 中,然后递归调用函数 $dfs(i + 1, s - candidates[i])$,然后将当前数字从搜索路径 $t$ 中移除。如果我们不选择当前数字,那么我们可以跳过与当前数字相同的所有数字,然后递归调用函数 $dfs(j, s)$,其中 $j$ 为第一个与当前数字不同的数字的下标。
314+
315+
时间复杂度 $O(2^n \times n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $candidates$ 的长度。由于剪枝,实际的时间复杂度要远小于 $O(2^n \times n)$。
314316

315317
<!-- tabs:start -->
316318

solution/0000-0099/0040.Combination Sum II/README_EN.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
## Solutions
5050

51-
### Solution 1: Sorting + Pruning + Backtracking (Two Implementations)
51+
### Solution 1: Sorting + Pruning + Backtracking
5252

5353
We can first sort the array to facilitate pruning and skipping duplicate numbers.
5454

@@ -306,7 +306,11 @@ public class Solution {
306306

307307
<!-- tabs:end -->
308308

309-
### Solution 2
309+
### Solution 2: Sorting + Pruning + Backtracking(Another Form)
310+
311+
We can also change the implementation logic of the function $dfs(i, s)$ to another form. If we choose the current number, we add the current number to the search path $t$, then recursively call the function $dfs(i + 1, s - candidates[i])$, and after the recursion ends, we remove the current number from the search path $t$. If we do not choose the current number, we can skip all numbers that are the same as the current number, then recursively call the function $dfs(j, s)$, where $j$ is the index of the first number that is different from the current number.
312+
313+
The time complexity is $O(2^n \times n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $candidates$. Due to pruning, the actual time complexity is much less than $O(2^n \times n)$.
310314

311315
<!-- tabs:start -->
312316

solution/0000-0099/0041.First Missing Positive/README.md

+25-58
Original file line numberDiff line numberDiff line change
@@ -178,80 +178,47 @@ impl Solution {
178178
```cs
179179
public class Solution {
180180
public int FirstMissingPositive(int[] nums) {
181-
var i = 0;
182-
while (i < nums.Length)
183-
{
184-
if (nums[i] > 0 && nums[i] <= nums.Length)
185-
{
186-
var index = nums[i] -1;
187-
if (index != i && nums[index] != nums[i])
188-
{
189-
var temp = nums[i];
190-
nums[i] = nums[index];
191-
nums[index] = temp;
192-
}
193-
else
194-
{
195-
++i;
196-
}
197-
}
198-
else
199-
{
200-
++i;
181+
int n = nums.Length;
182+
for (int i = 0; i < n; ++i) {
183+
while (nums[i] >= 1 && nums[i] <= n && nums[i] != nums[nums[i] - 1]) {
184+
Swap(nums, i, nums[i] - 1);
201185
}
202186
}
203-
204-
for (i = 0; i < nums.Length; ++i)
205-
{
206-
if (nums[i] != i + 1)
207-
{
187+
for (int i = 0; i < n; ++i) {
188+
if (i + 1 != nums[i]) {
208189
return i + 1;
209190
}
210191
}
211-
return nums.Length + 1;
192+
return n + 1;
193+
}
194+
195+
private void Swap(int[] nums, int i, int j) {
196+
int t = nums[i];
197+
nums[i] = nums[j];
198+
nums[j] = t;
212199
}
213200
}
214201
```
215202

216203
```c
217204
int firstMissingPositive(int* nums, int numsSize) {
218-
219-
int Max = nums[0], i, *Count;
220-
221-
for (i = 1; i < numsSize; i++) {
222-
Max = (Max < nums[i]) ? nums[i] : Max;
223-
}
224-
225-
Count = (int*) calloc(Max + 1, sizeof(int));
226-
for (i = 0; i < numsSize; i++) {
227-
if (nums[i] > 0) {
228-
Count[nums[i]]++;
205+
for (int i = 0; i < numsSize; ++i) {
206+
while (nums[i] >= 1 && nums[i] <= numsSize && nums[i] != nums[nums[i] - 1]) {
207+
swap(&nums[i], &nums[nums[i] - 1]);
229208
}
230209
}
231-
232-
i = 1;
233-
while (Count[i] != 0) {
234-
i++;
210+
for (int i = 0; i < numsSize; ++i) {
211+
if (i + 1 != nums[i]) {
212+
return i + 1;
213+
}
235214
}
236-
237-
return i;
215+
return numsSize + 1;
238216
}
239-
```
240-
241-
<!-- tabs:end -->
242-
243-
### 方法二
244-
245-
<!-- tabs:start -->
246217

247-
```ts
248-
function firstMissingPositive(nums: number[]): number {
249-
const set = new Set(nums);
250-
let ans = 1;
251-
while (true) {
252-
if (!set.has(ans)) return ans;
253-
ans++;
254-
}
218+
void swap(int* a, int* b) {
219+
int t = *a;
220+
*a = *b;
221+
*b = t;
255222
}
256223
```
257224

solution/0000-0099/0041.First Missing Positive/README_EN.md

+25-58
Original file line numberDiff line numberDiff line change
@@ -178,80 +178,47 @@ impl Solution {
178178
```cs
179179
public class Solution {
180180
public int FirstMissingPositive(int[] nums) {
181-
var i = 0;
182-
while (i < nums.Length)
183-
{
184-
if (nums[i] > 0 && nums[i] <= nums.Length)
185-
{
186-
var index = nums[i] -1;
187-
if (index != i && nums[index] != nums[i])
188-
{
189-
var temp = nums[i];
190-
nums[i] = nums[index];
191-
nums[index] = temp;
192-
}
193-
else
194-
{
195-
++i;
196-
}
197-
}
198-
else
199-
{
200-
++i;
181+
int n = nums.Length;
182+
for (int i = 0; i < n; ++i) {
183+
while (nums[i] >= 1 && nums[i] <= n && nums[i] != nums[nums[i] - 1]) {
184+
Swap(nums, i, nums[i] - 1);
201185
}
202186
}
203-
204-
for (i = 0; i < nums.Length; ++i)
205-
{
206-
if (nums[i] != i + 1)
207-
{
187+
for (int i = 0; i < n; ++i) {
188+
if (i + 1 != nums[i]) {
208189
return i + 1;
209190
}
210191
}
211-
return nums.Length + 1;
192+
return n + 1;
193+
}
194+
195+
private void Swap(int[] nums, int i, int j) {
196+
int t = nums[i];
197+
nums[i] = nums[j];
198+
nums[j] = t;
212199
}
213200
}
214201
```
215202

216203
```c
217204
int firstMissingPositive(int* nums, int numsSize) {
218-
219-
int Max = nums[0], i, *Count;
220-
221-
for (i = 1; i < numsSize; i++) {
222-
Max = (Max < nums[i]) ? nums[i] : Max;
223-
}
224-
225-
Count = (int*) calloc(Max + 1, sizeof(int));
226-
for (i = 0; i < numsSize; i++) {
227-
if (nums[i] > 0) {
228-
Count[nums[i]]++;
205+
for (int i = 0; i < numsSize; ++i) {
206+
while (nums[i] >= 1 && nums[i] <= numsSize && nums[i] != nums[nums[i] - 1]) {
207+
swap(&nums[i], &nums[nums[i] - 1]);
229208
}
230209
}
231-
232-
i = 1;
233-
while (Count[i] != 0) {
234-
i++;
210+
for (int i = 0; i < numsSize; ++i) {
211+
if (i + 1 != nums[i]) {
212+
return i + 1;
213+
}
235214
}
236-
237-
return i;
215+
return numsSize + 1;
238216
}
239-
```
240-
241-
<!-- tabs:end -->
242-
243-
### Solution 2
244-
245-
<!-- tabs:start -->
246217

247-
```ts
248-
function firstMissingPositive(nums: number[]): number {
249-
const set = new Set(nums);
250-
let ans = 1;
251-
while (true) {
252-
if (!set.has(ans)) return ans;
253-
ans++;
254-
}
218+
void swap(int* a, int* b) {
219+
int t = *a;
220+
*a = *b;
221+
*b = t;
255222
}
256223
```
257224
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
int firstMissingPositive(int* nums, int numsSize) {
2-
3-
int Max = nums[0], i, *Count;
4-
5-
for (i = 1; i < numsSize; i++) {
6-
Max = (Max < nums[i]) ? nums[i] : Max;
7-
}
8-
9-
Count = (int*) calloc(Max + 1, sizeof(int));
10-
for (i = 0; i < numsSize; i++) {
11-
if (nums[i] > 0) {
12-
Count[nums[i]]++;
2+
for (int i = 0; i < numsSize; ++i) {
3+
while (nums[i] >= 1 && nums[i] <= numsSize && nums[i] != nums[nums[i] - 1]) {
4+
swap(&nums[i], &nums[nums[i] - 1]);
135
}
146
}
15-
16-
i = 1;
17-
while (Count[i] != 0) {
18-
i++;
7+
for (int i = 0; i < numsSize; ++i) {
8+
if (i + 1 != nums[i]) {
9+
return i + 1;
10+
}
1911
}
12+
return numsSize + 1;
13+
}
2014

21-
return i;
15+
void swap(int* a, int* b) {
16+
int t = *a;
17+
*a = *b;
18+
*b = t;
2219
}

0 commit comments

Comments
 (0)