This commit is contained in:
krahets
2023-08-17 05:12:05 +08:00
parent f0826da7f6
commit 97c532b228
67 changed files with 1481 additions and 1066 deletions
@@ -197,7 +197,7 @@ comments: true
![在前序遍历中搜索节点](backtracking_algorithm.assets/preorder_find_nodes.png)
<p align="center"> Fig. 在前序遍历中搜索节点 </p>
<p align="center"> 图:在前序遍历中搜索节点 </p>
## 13.1.1. &nbsp; 尝试与回退
@@ -501,6 +501,8 @@ comments: true
=== "<11>"
![preorder_find_paths_step11](backtracking_algorithm.assets/preorder_find_paths_step11.png)
<p align="center"> 图:尝试与回退 </p>
## 13.1.2. &nbsp; 剪枝
复杂的回溯问题通常包含一个或多个约束条件,**约束条件通常可用于“剪枝”**。
@@ -797,7 +799,7 @@ comments: true
![根据约束条件剪枝](backtracking_algorithm.assets/preorder_find_constrained_paths.png)
<p align="center"> Fig. 根据约束条件剪枝 </p>
<p align="center"> 图:根据约束条件剪枝 </p>
## 13.1.3. &nbsp; 框架代码
@@ -1657,7 +1659,7 @@ comments: true
![保留与删除 return 的搜索过程对比](backtracking_algorithm.assets/backtrack_remove_return_or_not.png)
<p align="center"> Fig. 保留与删除 return 的搜索过程对比 </p>
<p align="center"> 图:保留与删除 return 的搜索过程对比 </p>
相比基于前序遍历的代码实现,基于回溯算法框架的代码实现虽然显得啰嗦,但通用性更好。实际上,**许多回溯问题都可以在该框架下解决**。我们只需根据具体问题来定义 `state` 和 `choices` ,并实现框架中的各个方法即可。
+4 -4
View File
@@ -12,13 +12,13 @@ comments: true
![4 皇后问题的解](n_queens_problem.assets/solution_4_queens.png)
<p align="center"> Fig. 4 皇后问题的解 </p>
<p align="center"> 图:4 皇后问题的解 </p>
本题共包含三个约束条件:**多个皇后不能在同一行、同一列、同一对角线**。值得注意的是,对角线分为主对角线 `\` 和次对角线 `/` 两种。
![n 皇后问题的约束条件](n_queens_problem.assets/n_queens_constraints.png)
<p align="center"> Fig. n 皇后问题的约束条件 </p>
<p align="center"> 图:n 皇后问题的约束条件 </p>
### 逐行放置策略
@@ -30,7 +30,7 @@ comments: true
![逐行放置策略](n_queens_problem.assets/n_queens_placing.png)
<p align="center"> Fig. 逐行放置策略 </p>
<p align="center"> 图:逐行放置策略 </p>
本质上看,**逐行放置策略起到了剪枝的作用**,它避免了同一行出现多个皇后的所有搜索分支。
@@ -46,7 +46,7 @@ comments: true
![处理列约束和对角线约束](n_queens_problem.assets/n_queens_cols_diagonals.png)
<p align="center"> Fig. 处理列约束和对角线约束 </p>
<p align="center"> 图:处理列约束和对角线约束 </p>
### 代码实现
+5 -5
View File
@@ -32,7 +32,7 @@ comments: true
![全排列的递归树](permutations_problem.assets/permutations_i.png)
<p align="center"> Fig. 全排列的递归树 </p>
<p align="center"> 图:全排列的递归树 </p>
### 重复选择剪枝
@@ -45,7 +45,7 @@ comments: true
![全排列剪枝示例](permutations_problem.assets/permutations_i_pruning.png)
<p align="center"> Fig. 全排列剪枝示例 </p>
<p align="center"> 图:全排列剪枝示例 </p>
观察上图发现,该剪枝操作将搜索空间大小从 $O(n^n)$ 降低至 $O(n!)$ 。
@@ -483,7 +483,7 @@ comments: true
![重复排列](permutations_problem.assets/permutations_ii.png)
<p align="center"> Fig. 重复排列 </p>
<p align="center"> 图:重复排列 </p>
那么如何去除重复的排列呢?最直接地,考虑借助一个哈希表,直接对排列结果进行去重。然而这样做不够优雅,**因为生成重复排列的搜索分支是没有必要的,应当被提前识别并剪枝**,这样可以进一步提升算法效率。
@@ -497,7 +497,7 @@ comments: true
![重复排列剪枝](permutations_problem.assets/permutations_ii_pruning.png)
<p align="center"> Fig. 重复排列剪枝 </p>
<p align="center"> 图:重复排列剪枝 </p>
### 代码实现
@@ -914,4 +914,4 @@ comments: true
![两种剪枝条件的作用范围](permutations_problem.assets/permutations_ii_pruning_summary.png)
<p align="center"> Fig. 两种剪枝条件的作用范围 </p>
<p align="center"> 图:两种剪枝条件的作用范围 </p>
+5 -5
View File
@@ -438,7 +438,7 @@ comments: true
![子集搜索与越界剪枝](subset_sum_problem.assets/subset_sum_i_naive.png)
<p align="center"> Fig. 子集搜索与越界剪枝 </p>
<p align="center"> 图:子集搜索与越界剪枝 </p>
为了去除重复子集,**一种直接的思路是对结果列表进行去重**。但这个方法效率很低,因为:
@@ -460,7 +460,7 @@ comments: true
![不同选择顺序导致的重复子集](subset_sum_problem.assets/subset_sum_i_pruning.png)
<p align="center"> Fig. 不同选择顺序导致的重复子集 </p>
<p align="center"> 图:不同选择顺序导致的重复子集 </p>
总结来看,给定输入数组 $[x_1, x_2, \cdots, x_n]$ ,设搜索过程中的选择序列为 $[x_{i_1}, x_{i_2}, \cdots , x_{i_m}]$ ,则该选择序列需要满足 $i_1 \leq i_2 \leq \cdots \leq i_m$ ,**不满足该条件的选择序列都会造成重复,应当剪枝**。
@@ -916,7 +916,7 @@ comments: true
![子集和 I 回溯过程](subset_sum_problem.assets/subset_sum_i.png)
<p align="center"> Fig. 子集和 I 回溯过程 </p>
<p align="center"> 图:子集和 I 回溯过程 </p>
## 13.3.2. &nbsp; 考虑重复元素的情况
@@ -930,7 +930,7 @@ comments: true
![相等元素导致的重复子集](subset_sum_problem.assets/subset_sum_ii_repeat.png)
<p align="center"> Fig. 相等元素导致的重复子集 </p>
<p align="center"> 图:相等元素导致的重复子集 </p>
### 相等元素剪枝
@@ -1438,4 +1438,4 @@ comments: true
![子集和 II 回溯过程](subset_sum_problem.assets/subset_sum_ii.png)
<p align="center"> Fig. 子集和 II 回溯过程 </p>
<p align="center"> 图:子集和 II 回溯过程 </p>