Skip to content

Commit

Permalink
更新题解列表
Browse files Browse the repository at this point in the history
  • Loading branch information
itcharge committed Dec 22, 2023
1 parent 4f25194 commit eea9d75
Show file tree
Hide file tree
Showing 13 changed files with 250 additions and 118 deletions.
32 changes: 16 additions & 16 deletions Solutions/0091. 解码方法.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@

## 题目大意

**描述**:给定一个数字字符串 `s`。该字符串已经按照下面的映射关系进行了编码:
**描述**:给定一个数字字符串 $s$。该字符串已经按照下面的映射关系进行了编码:

- `A` 映射为 `1`
- `B` 映射为 `2`
- `A` 映射为 $1$
- `B` 映射为 $2$
- ...
- `Z` 映射为 `26`
- `Z` 映射为 $26$

基于上述映射的方法,现在对字符串 `s` 进行「解码」。即从数字到字母进行反向映射。比如 `"11106"` 可以映射为:
基于上述映射的方法,现在对字符串 $s$ 进行「解码」。即从数字到字母进行反向映射。比如 `"11106"` 可以映射为:

- `"AAJF"`,将消息分组为 `(1 1 10 6)`
- `"KJF"`,将消息分组为 `(11 10 6)`
- `"AAJF"`,将消息分组为 $(1 1 10 6)$
- `"KJF"`,将消息分组为 $(11 10 6)$

**要求**:计算出共有多少种可能的解码方案。

**说明**

- $1 \le s.length \le 100$。
- `s` 只包含数字,并且可能包含前导零。
- 题目数据保证答案肯定是一个 `32` 位的整数。
- $s$ 只包含数字,并且可能包含前导零。
- 题目数据保证答案肯定是一个 $32$ 位的整数。

**示例**

Expand All @@ -45,14 +45,14 @@

###### 2. 定义状态

定义状态 `dp[i]` 表示为:字符串 `s``i` 个字符构成的字符串可能构成的翻译方案数。
定义状态 $dp[i]$ 表示为:字符串 $s$$i$ 个字符构成的字符串可能构成的翻译方案数。

###### 3. 状态转移方程

`dp[i]` 的来源有两种情况:
$dp[i]$ 的来源有两种情况:

1. 使用了一个字符,对 `s[i]` 进行翻译。只要 `s[i] != 0`,就可以被翻译为 `A` ~ `I` 的某个字母,此时方案数为 `dp[i] = dp[i - 1]`
2. 使用了两个字符,对 `s[i - 1]``s[i]` 进行翻译,只有 `s[i - 1] != 0`,且 `s[i - 1]``s[i]` 组成的整数必须小于等于 `26` 才能翻译,可以翻译为 `J` ~ `Z` 中的某字母,此时方案数为 `dp[i] = dp[i - 2]`
1. 使用了一个字符,对 $s[i]$ 进行翻译。只要 $s[i] != 0$,就可以被翻译为 `A` ~ `I` 的某个字母,此时方案数为 $dp[i] = dp[i - 1]$
2. 使用了两个字符,对 $s[i - 1]$$s[i]$ 进行翻译,只有 $s[i - 1] != 0$,且 $s[i - 1]$$s[i]$ 组成的整数必须小于等于 $26$ 才能翻译,可以翻译为 `J` ~ `Z` 中的某字母,此时方案数为 $dp[i] = dp[i - 2]$

这两种情况有可能是同时存在的,也有可能都不存在。在进行转移的时候,将符合要求的方案数累加起来即可。

Expand All @@ -62,12 +62,12 @@ $dp[i] += \begin{cases} \begin{array} \ dp[i-1] & s[i] \ne 0 \cr dp[i-2] & s[i-

###### 4. 初始条件

- 字符串为空时,只有一个翻译方案,翻译为空字符串,即 `dp[0] = 1`
- 字符串只有一个字符时,需要考虑该字符是否为 `0`,不为 `0` 的话,`dp[1] = 1`,为 `0` 的话,`dp[0] = 0`
- 字符串为空时,只有一个翻译方案,翻译为空字符串,即 $dp[0] = 1$
- 字符串只有一个字符时,需要考虑该字符是否为 $0$,不为 $0$ 的话,$dp[1] = 1$,为 $0$ 的话,$dp[0] = 0$

###### 5. 最终结果

根据我们之前定义的状态,`dp[i]` 表示为:字符串 `s``i` 个字符构成的字符串可能构成的翻译方案数。则最终结果为 `dp[size]``size` 为字符串长度。
根据我们之前定义的状态,$dp[i]$ 表示为:字符串 $s$$i$ 个字符构成的字符串可能构成的翻译方案数。则最终结果为 $dp[size]$,$size$ 为字符串长度。


### 思路 1:动态规划代码
Expand Down
43 changes: 37 additions & 6 deletions Solutions/0095. 不同的二叉搜索树 II.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,48 @@

## 题目大意

给定一个整数 `n`,请返回以 `1``n` 为节点构成的「二叉搜索树」,可以按任意顺序返回答案。
**描述**:给定一个整数 $n$。

**要求**:请生成返回以 $1$ 到 $n$ 为节点构成的「二叉搜索树」,可以按任意顺序返回答案。

**说明**

- $1 \le n \le 8$。

**示例**

- 示例 1:

![](https://assets.leetcode.com/uploads/2021/01/18/uniquebstn3.jpg)

```python
输入:n = 3
输出:[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]
```

- 示例 2:

```python
输入:n = 1
输出:[[1]]
```

## 解题思路

如果根节点为 `i`,则左子树的节点为 `(1, 2, ..., i - 1)`,右子树的节点为 `(i + 1, i + 2, ..., n)`。可以递归的构建二叉树。
### 思路 1:递归遍历

如果根节点为 $i$,则左子树的节点为 $(1, 2, ..., i - 1)$,右子树的节点为 $(i + 1, i + 2, ..., n)$。可以递归的构建二叉树。

定义递归函数 `generateTrees(start, end)`,表示生成 `[left, ..., right]` 构成的所有可能的二叉搜索树。
定义递归函数 `generateTrees(start, end)`,表示生成 $[left, ..., right]$ 构成的所有可能的二叉搜索树。

- 如果 `start > end`,返回 [None]
- 如果 $start > end$,返回 `[None]`
- 初始化存放所有可能二叉搜索树的数组。
- 遍历 `[left, ..., right]` 的每一个节点 `i`,将其作为根节点。
- 遍历 $[left, ..., right]$ 的每一个节点 $i$,将其作为根节点。
- 递归构建左右子树。
- 将所有符合要求的左右子树组合起来,将其加入到存放二叉搜索树的数组中。
- 返回存放二叉搜索树的数组。

## 代码
### 思路 1:代码

```python
class Solution:
Expand All @@ -45,3 +71,8 @@ class Solution:
return generateTrees(1, n)
```

### 思路 1:复杂度分析

- **时间复杂度**:$O(C_n)$,其中 $C_n$ 是第 $n$ 个卡特兰数。
- **空间复杂度**:$O(C_n)$,其中 $C_n$ 是第 $n$ 个卡特兰数。

25 changes: 16 additions & 9 deletions Solutions/0118. 杨辉三角.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

## 题目大意

**描述**:给定一个整数 `numRows`
**描述**:给定一个整数 $numRows$

**要求**:生成前 `numRows` 行的杨辉三角。
**要求**:生成前 $numRows$ 行的杨辉三角。

**说明**

Expand All @@ -30,6 +30,13 @@
]
```

- 示例 2:

```python
输入: numRows = 1
输出: [[1]]
```

## 解题思路

### 思路 1:动态规划
Expand All @@ -40,16 +47,16 @@

###### 2. 定义状态

定义状态 `dp[i][j]` 为:杨辉三角第 `i` 行、第 `j` 列位置上的值。
定义状态 $dp[i][j]$ 为:杨辉三角第 $i$ 行、第 $j$ 列位置上的值。

###### 3. 状态转移方程

根据观察,很容易得出状态转移方程为:`dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]`,此时 `i > 0j > 0`
根据观察,很容易得出状态转移方程为:$dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]$,此时 $i > 0$,$j > 0$

###### 4. 初始条件

- 每一行第一列都为 `1`,即 `dp[i][0] = 1`
- 每一行最后一列都为 `1`,即 `dp[i][i] = 1`
- 每一行第一列都为 $1$,即 $dp[i][0] = 1$
- 每一行最后一列都为 $1$,即 $dp[i][i] = 1$

###### 5. 最终结果

Expand Down Expand Up @@ -83,15 +90,15 @@ class Solution:

### 思路 2:动态规划 + 滚动数组优化

因为 `dp[i][j]` 仅依赖于上一行(第 `i - 1` 行)的 `dp[i - 1][j - 1]``dp[i - 1][j]`,所以我们没必要保存所有阶段的状态,只需要保存上一阶段的所有状态和当前阶段的所有状态就可以了,这样使用两个一维数组分别保存相邻两个阶段的所有状态就可以实现了。
因为 $dp[i][j]$ 仅依赖于上一行(第 $i - 1$ 行)的 $dp[i - 1][j - 1]$$dp[i - 1][j]$,所以我们没必要保存所有阶段的状态,只需要保存上一阶段的所有状态和当前阶段的所有状态就可以了,这样使用两个一维数组分别保存相邻两个阶段的所有状态就可以实现了。

其实我们还可以进一步进行优化,即我们只需要使用一个一维数组保存上一阶段的所有状态。

定义 `dp[j]` 为杨辉三角第 `i` 行第 `j` 列位置上的值。则第 `i + 1` 行、第 `j` 列的值可以通过 `dp[j]` + `dp[j - 1]` 所得到。
定义 $dp[j]$ 为杨辉三角第 $i$ 行第 $j$ 列位置上的值。则第 $i + 1$ 行、第 $j$ 列的值可以通过 $dp[j]$ + $dp[j - 1]$ 所得到。

这样我们就可以对这个一维数组保存的「上一阶段的所有状态值」进行逐一计算,从而获取「当前阶段的所有状态值」。

需要注意:本题在计算的时候需要从右向左依次遍历每个元素位置,这是因为如果从左向右遍历,如果当前元素 `dp[j]` 已经更新为当前阶段第 `j` 列位置的状态值之后,右侧 `dp[j + 1]` 想要更新的话,需要的是上一阶段的状态值 `dp[j]`,而此时 `dp[j]` 已经更新了,会破坏当前阶段的状态值。而如果用从右向左的顺序,则不会出现该问题。
需要注意:本题在计算的时候需要从右向左依次遍历每个元素位置,这是因为如果从左向右遍历,如果当前元素 $dp[j]$ 已经更新为当前阶段第 $j$ 列位置的状态值之后,右侧 $dp[j + 1]$ 想要更新的话,需要的是上一阶段的状态值 $dp[j]$,而此时 $dp[j]$ 已经更新了,会破坏当前阶段的状态值。而如果用从右向左的顺序,则不会出现该问题。

### 思路 2:动态规划 + 滚动数组优化代码

Expand Down
22 changes: 11 additions & 11 deletions Solutions/0119. 杨辉三角 II.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

## 题目大意

**描述**:给定一个非负整数 `rowIndex`
**描述**:给定一个非负整数 $rowIndex$

**要求**:返回杨辉三角的第 `rowIndex` 行。
**要求**:返回杨辉三角的第 $rowIndex$ 行。

**说明**

Expand All @@ -27,28 +27,28 @@

### 思路 1:动态规划

因为这道题是从 `0` 行开始计算,则可以先将 `rowIndex``1`,计算出总共的行数,即 `numRows = rowIndex + 1`
因为这道题是从 $0$ 行开始计算,则可以先将 $rowIndex$$1$,计算出总共的行数,即 $numRows = rowIndex + 1$

###### 1. 划分阶段

按照行数进行阶段划分。

###### 2. 定义状态

定义状态 `dp[i][j]` 为:杨辉三角第 `i` 行、第 `j` 列位置上的值。
定义状态 $dp[i][j]$ 为:杨辉三角第 $i$ 行、第 $j$ 列位置上的值。

###### 3. 状态转移方程

根据观察,很容易得出状态转移方程为:`dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]`,此时 `i > 0j > 0`
根据观察,很容易得出状态转移方程为:$dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]$,此时 $i > 0$,$j > 0$

###### 4. 初始条件

- 每一行第一列都为 `1`,即 `dp[i][0] = 1`
- 每一行最后一列都为 `1`,即 `dp[i][i] = 1`
- 每一行第一列都为 $1$,即 $dp[i][0] = 1$
- 每一行最后一列都为 $1$,即 $dp[i][i] = 1$

###### 5. 最终结果

根据题意和状态定义,将 `dp` 最后一行返回。
根据题意和状态定义,将 $dp$ 最后一行返回。

### 思路 1:代码

Expand Down Expand Up @@ -79,15 +79,15 @@ class Solution:

### 思路 2:动态规划 + 滚动数组优化

因为 `dp[i][j]` 仅依赖于上一行(第 `i - 1` 行)的 `dp[i - 1][j - 1]``dp[i - 1][j]`,所以我们没必要保存所有阶段的状态,只需要保存上一阶段的所有状态和当前阶段的所有状态就可以了,这样使用两个一维数组分别保存相邻两个阶段的所有状态就可以实现了。
因为 $dp[i][j]$ 仅依赖于上一行(第 $i - 1$ 行)的 $dp[i - 1][j - 1]$$dp[i - 1][j]$,所以我们没必要保存所有阶段的状态,只需要保存上一阶段的所有状态和当前阶段的所有状态就可以了,这样使用两个一维数组分别保存相邻两个阶段的所有状态就可以实现了。

其实我们还可以进一步进行优化,即我们只需要使用一个一维数组保存上一阶段的所有状态。

定义 `dp[j]` 为杨辉三角第 `i` 行第 `j` 列位置上的值。则第 `i + 1` 行、第 `j` 列的值可以通过 `dp[j]` + `dp[j - 1]` 所得到。
定义 $dp[j]$ 为杨辉三角第 $i$ 行第 $j$ 列位置上的值。则第 $i + 1$ 行、第 $j$ 列的值可以通过 $dp[j]$ + $dp[j - 1]$ 所得到。

这样我们就可以对这个一维数组保存的「上一阶段的所有状态值」进行逐一计算,从而获取「当前阶段的所有状态值」。

需要注意:本题在计算的时候需要从右向左依次遍历每个元素位置,这是因为如果从左向右遍历,如果当前元素 `dp[j]` 已经更新为当前阶段第 `j` 列位置的状态值之后,右侧 `dp[j + 1]` 想要更新的话,需要的是上一阶段的状态值 `dp[j]`,而此时 `dp[j]` 已经更新了,会破坏当前阶段的状态值。而是用从左向左的顺序,则不会出现该问题。
需要注意:本题在计算的时候需要从右向左依次遍历每个元素位置,这是因为如果从左向右遍历,如果当前元素 $dp[j]$ 已经更新为当前阶段第 $j$ 列位置的状态值之后,右侧 $dp[j + 1]$ 想要更新的话,需要的是上一阶段的状态值 $dp[j]$,而此时 $dp[j]$ 已经更新了,会破坏当前阶段的状态值。而是用从左向左的顺序,则不会出现该问题。

### 思路 2:动态规划 + 滚动数组优化代码

Expand Down
21 changes: 14 additions & 7 deletions Solutions/0120. 三角形最小路径和.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

## 题目大意

**描述**:给定一个代表三角形的二维数组 `triangle``triangle` 共有 `n` 行,其中第 `i` 行(从 `0` 开始编号)包含了 `i + 1` 个数。
**描述**:给定一个代表三角形的二维数组 $triangle$,$triangle$ 共有 $n$ 行,其中第 $i$ 行(从 $0$ 开始编号)包含了 $i + 1$ 个数。

我们每一步只能从当前位置移动到下一行中相邻的节点上。也就是说,如果正位于第 `i` 行第 `j` 列的节点,那么下一步可以移动到第 `i + 1` 行第 `j` 列的位置上,或者第 `i + 1` 行,第 `j + 1` 列的位置上。
我们每一步只能从当前位置移动到下一行中相邻的节点上。也就是说,如果正位于第 $i$ 行第 $j$ 列的节点,那么下一步可以移动到第 $i + 1$ 行第 $j$ 列的位置上,或者第 $i + 1$ 行,第 $j + 1$ 列的位置上。

**要求**:找出自顶向下的最小路径和。

Expand All @@ -33,6 +33,13 @@
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
```

- 示例 2:

```python
输入:triangle = [[-10]]
输出:-10
```

## 解题思路

### 思路 1:动态规划
Expand All @@ -43,21 +50,21 @@

###### 2. 定义状态

定义状态 `dp[i][j]` 表示为:从顶部走到第 `i` 行(从 `0` 开始编号)、第 `j` 列的位置时的最小路径和。
定义状态 $dp[i][j]$ 表示为:从顶部走到第 $i$ 行(从 $0$ 开始编号)、第 $j$ 列的位置时的最小路径和。

###### 3. 状态转移方程

由于每一步只能从当前位置移动到下一行中相邻的节点上,想要移动到第 `i` 行、第 `j` 列的位置,那么上一步只能在第 `i - 1` 行、第 `j - 1` 列的位置上,或者在第 `i - 1` 行、第 `j` 列的位置上。则状态转移方程为:
由于每一步只能从当前位置移动到下一行中相邻的节点上,想要移动到第 $i$ 行、第 $j$ 列的位置,那么上一步只能在第 $i - 1$ 行、第 $j - 1$ 列的位置上,或者在第 $i - 1$ 行、第 $j$ 列的位置上。则状态转移方程为:

`dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle[i][j]`。其中 `triangle[i][j]` 表示第 `i` 行、第 `j` 列位置上的元素值。
$dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle[i][j]$。其中 $triangle[i][j]$ 表示第 $i$ 行、第 $j$ 列位置上的元素值。

###### 4. 初始条件

在第 `0` 行、第 `j` 列时,最小路径和为 `triangle[0][0]`,即 `dp[0][0] = triangle[0][0]`
在第 $0$ 行、第 $j$ 列时,最小路径和为 $triangle[0][0]$,即 $dp[0][0] = triangle[0][0]$

###### 5. 最终结果

根据我们之前定义的状态,`dp[i][j]` 表示为:从顶部走到第 `i` 行(从 `0` 开始编号)、第 `j` 列的位置时的最小路径和。为了计算出最小路径和,则需要再遍历一遍 `dp[size - 1]` 行的每一列,求出最小值即为最终结果。
根据我们之前定义的状态,$dp[i][j]$ 表示为:从顶部走到第 $i$ 行(从 $0$ 开始编号)、第 $j$ 列的位置时的最小路径和。为了计算出最小路径和,则需要再遍历一遍 $dp[size - 1]$ 行的每一列,求出最小值即为最终结果。

### 思路 1:动态规划代码

Expand Down
2 changes: 1 addition & 1 deletion Solutions/0241. 为运算表达式设计优先级.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,5 @@ class Solution:

### 思路 1:复杂度分析

- **时间复杂度**:$O(C_n)$,其中 $n$ 为结果数组的大小,$C_n$ 是第 $k$ 个卡特兰数。
- **时间复杂度**:$O(C_n)$,其中 $n$ 为结果数组的大小,$C_n$ 是第 $n$ 个卡特兰数。
- **空间复杂度**:$O(C_n)$。
2 changes: 1 addition & 1 deletion Solutions/0354. 俄罗斯套娃信封问题.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

## 题目大意

给定一个二维整数数组 envelopes 表示信封,其中 `envelopes[i] = [wi, hi]`,表示第 i 个信封的宽度 wi 和高度 hi
给定一个二维整数数组 envelopes 表示信封,其中 $envelopes[i] = [wi, hi]$,表示第 $i$ 个信封的宽度 $w_i$ 和高度 $h_i$

当一个信封的宽度和高度比另一个信封大时,则小的信封可以放进大信封里,就像俄罗斯套娃一样。

Expand Down
Loading

0 comments on commit eea9d75

Please sign in to comment.