Fix a definition.

This commit is contained in:
krahets
2023-08-27 00:50:18 +08:00
parent debf42b189
commit 9731a46d67
85 changed files with 167 additions and 159 deletions

View File

@@ -110,7 +110,7 @@ $$
![爬楼梯最小代价的动态规划过程](dp_problem_features.assets/min_cost_cs_dp.png)
本题也可以进行状态压缩,将一维压缩至零维,使得空间复杂度从 $O(n)$ 降低至 $O(1)$ 。
本题也可以进行空间优化,将一维压缩至零维,使得空间复杂度从 $O(n)$ 降低至 $O(1)$ 。
=== "Java"

View File

@@ -374,7 +374,7 @@ $$
=== "<12>"
![min_path_sum_dp_step12](dp_solution_pipeline.assets/min_path_sum_dp_step12.png)
### 状态压缩
### 空间优化
由于每个格子只与其左边和上边的格子有关,因此我们可以只用一个单行数组来实现 $dp$ 表。

View File

@@ -186,7 +186,7 @@ $$
=== "<15>"
![edit_distance_dp_step15](edit_distance_problem.assets/edit_distance_dp_step15.png)
### 状态压缩
### 空间优化
由于 $dp[i,j]$ 是由上方 $dp[i-1, j]$ 、左方 $dp[i, j-1]$ 、左上方状态 $dp[i-1, j-1]$ 转移而来,而正序遍历会丢失左上方 $dp[i-1, j-1]$ ,倒序遍历无法提前构建 $dp[i, j-1]$ ,因此两种遍历顺序都不可取。

View File

@@ -442,7 +442,7 @@ $$
- 将最小子问题对应的状态(即第 $1$ , $2$ 阶楼梯)称为「初始状态」。
- 将递推公式 $dp[i] = dp[i-1] + dp[i-2]$ 称为「状态转移方程」。
## 状态压缩
## 空间优化
细心的你可能发现,**由于 $dp[i]$ 只与 $dp[i-1]$ 和 $dp[i-2]$ 有关,因此我们无须使用一个数组 `dp` 来存储所有子问题的解**,而只需两个变量滚动前进即可。
@@ -520,4 +520,4 @@ $$
观察以上代码,由于省去了数组 `dp` 占用的空间,因此空间复杂度从 $O(n)$ 降低至 $O(1)$ 。
**这种空间优化技巧被称为「状态压缩」**。在常见的动态规划问题中,当前状态仅与前面有限个状态有关,这时我们可以应用状态压缩,只保留必要的状态,通过“降维”来节省内存空间。
动态规划问题中,当前状态往往仅与前面有限个状态有关,这时我们可以只保留必要的状态,通过“降维”来节省内存空间。**这种空间优化技巧被称为“滚动变量”或“滚动数组”**。

View File

@@ -336,11 +336,11 @@ $$
=== "<14>"
![knapsack_dp_step14](knapsack_problem.assets/knapsack_dp_step14.png)
### 状态压缩
### 空间优化
由于每个状态都只与其上一行的状态有关,因此我们可以使用两个数组滚动前进,将空间复杂度从 $O(n^2)$ 将低至 $O(n)$ 。
进一步思考,我们是否可以仅用一个数组实现状态压缩呢?观察可知,每个状态都是由正上方或左上方的格子转移过来的。假设只有一个数组,当开始遍历第 $i$ 行时,该数组存储的仍然是第 $i-1$ 行的状态。
进一步思考,我们是否可以仅用一个数组实现空间优化呢?观察可知,每个状态都是由正上方或左上方的格子转移过来的。假设只有一个数组,当开始遍历第 $i$ 行时,该数组存储的仍然是第 $i-1$ 行的状态。
- 如果采取正序遍历,那么遍历到 $dp[i, j]$ 时,左上方 $dp[i-1, 1]$ ~ $dp[i-1, j-1]$ 值可能已经被覆盖,此时就无法得到正确的状态转移结果。
- 如果采取倒序遍历,则不会发生覆盖问题,状态转移可以正确进行。
@@ -348,7 +348,7 @@ $$
下图展示了在单个数组下从第 $i = 1$ 行转换至第 $i = 2$ 行的过程。请思考正序遍历和倒序遍历的区别。
=== "<1>"
![0-1 背包的状态压缩后的动态规划过程](knapsack_problem.assets/knapsack_dp_comp_step1.png)
![0-1 背包的空间优化后的动态规划过程](knapsack_problem.assets/knapsack_dp_comp_step1.png)
=== "<2>"
![knapsack_dp_comp_step2](knapsack_problem.assets/knapsack_dp_comp_step2.png)

View File

@@ -11,8 +11,8 @@
**背包问题**
- 背包问题是最典型的动态规划题目,具有 0-1 背包、完全背包、多重背包等变种问题。
- 0-1 背包的状态定义为前 $i$ 个物品在剩余容量为 $c$ 的背包中的最大价值。根据不放入背包和放入背包两种决策,可得到最优子结构,并构建出状态转移方程。在状态压缩中,由于每个状态依赖正上方和左上方的状态,因此需要倒序遍历列表,避免左上方状态被覆盖。
- 完全背包的每种物品的选取数量无限制,因此选择放入物品的状态转移与 0-1 背包不同。由于状态依赖于正上方和正左方的状态,因此在状态压缩中应当正序遍历。
- 0-1 背包的状态定义为前 $i$ 个物品在剩余容量为 $c$ 的背包中的最大价值。根据不放入背包和放入背包两种决策,可得到最优子结构,并构建出状态转移方程。在空间优化中,由于每个状态依赖正上方和左上方的状态,因此需要倒序遍历列表,避免左上方状态被覆盖。
- 完全背包的每种物品的选取数量无限制,因此选择放入物品的状态转移与 0-1 背包不同。由于状态依赖于正上方和正左方的状态,因此在空间优化中应当正序遍历。
- 零钱兑换问题是完全背包的一个变种。它从求“最大”价值变为求“最小”硬币数量,因此状态转移方程中的 $\max()$ 应改为 $\min()$ 。从求“不超过”背包容量到求“恰好”凑出目标金额,因此使用 $amt + 1$ 来表示“无法凑出目标金额”的无效解。
- 零钱兑换 II 问题从求“最少硬币数量”改为求“硬币组合数量”,状态转移方程相应地从 $\min()$ 改为求和运算符。
@@ -20,4 +20,4 @@
- 编辑距离Levenshtein 距离)用于衡量两个字符串之间的相似度,其定义为从一个字符串到另一个字符串的最小编辑步数,编辑操作包括添加、删除、替换。
- 编辑距离问题的状态定义为将 $s$ 的前 $i$ 个字符更改为 $t$ 的前 $j$ 个字符所需的最少编辑步数。当 $s[i] \ne t[j]$ 时,具有三种决策:添加、删除、替换,它们都有相应的剩余子问题。据此便可以找出最优子结构与构建状态转移方程。而当 $s[i] = t[j]$ 时,无须编辑当前字符。
- 在编辑距离中,状态依赖于其正上方、正左方、左上方的状态,因此状态压缩后正序或倒序遍历都无法正确地进行状态转移。为此,我们利用一个变量暂存左上方状态,从而转化到与完全背包等价的情况,可以在状态压缩后进行正序遍历。
- 在编辑距离中,状态依赖于其正上方、正左方、左上方的状态,因此空间优化后正序或倒序遍历都无法正确地进行状态转移。为此,我们利用一个变量暂存左上方状态,从而转化到与完全背包等价的情况,可以在空间优化后进行正序遍历。

View File

@@ -104,14 +104,14 @@ $$
[class]{}-[func]{unbounded_knapsack_dp}
```
### 状态压缩
### 空间优化
由于当前状态是从左边和上边的状态转移而来,**因此状态压缩后应该对 $dp$ 表中的每一行采取正序遍历**。
由于当前状态是从左边和上边的状态转移而来,**因此空间优化后应该对 $dp$ 表中的每一行采取正序遍历**。
这个遍历顺序与 0-1 背包正好相反。请借助下图来理解两者的区别。
=== "<1>"
![完全背包的状态压缩后的动态规划过程](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png)
![完全背包的空间优化后的动态规划过程](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png)
=== "<2>"
![unbounded_knapsack_dp_comp_step2](unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step2.png)
@@ -370,9 +370,9 @@ $$
=== "<15>"
![coin_change_dp_step15](unbounded_knapsack_problem.assets/coin_change_dp_step15.png)
### 状态压缩
### 空间优化
零钱兑换的状态压缩的处理方式和完全背包一致。
零钱兑换的空间优化的处理方式和完全背包一致。
=== "Java"
@@ -540,9 +540,9 @@ $$
[class]{}-[func]{coin_change_ii_dp}
```
### 状态压缩
### 空间优化
状态压缩处理方式相同,删除硬币维度即可。
空间优化处理方式相同,删除硬币维度即可。
=== "Java"