This commit is contained in:
krahets
2023-08-20 13:37:08 +08:00
parent 2e27ad1680
commit 44a8568356
32 changed files with 140 additions and 130 deletions
+5 -5
View File
@@ -36,7 +36,7 @@ comments: true
<p align="center"> 图:全排列的递归树 </p>
### 重复选择剪枝
### 1. &nbsp; 重复选择剪枝
为了实现每个元素只被选择一次,我们考虑引入一个布尔型数组 `selected` ,其中 `selected[i]` 表示 `choices[i]` 是否已被选择。剪枝的实现原理为:
@@ -51,7 +51,7 @@ comments: true
观察上图发现,该剪枝操作将搜索空间大小从 $O(n^n)$ 降低至 $O(n!)$ 。
### 代码实现
### 2. &nbsp; 代码实现
想清楚以上信息之后,我们就可以在框架代码中做“完形填空”了。为了缩短代码行数,我们不单独实现框架代码中的各个函数,而是将他们展开在 `backtrack()` 函数中。
@@ -489,7 +489,7 @@ comments: true
那么如何去除重复的排列呢?最直接地,考虑借助一个哈希表,直接对排列结果进行去重。然而这样做不够优雅,**因为生成重复排列的搜索分支是没有必要的,应当被提前识别并剪枝**,这样可以进一步提升算法效率。
### 相等元素剪枝
### 1. &nbsp; 相等元素剪枝
观察发现,在第一轮中,选择 $1$ 或选择 $\hat{1}$ 是等价的,在这两个选择之下生成的所有排列都是重复的。因此应该把 $\hat{1}$ 剪枝掉。
@@ -501,7 +501,7 @@ comments: true
<p align="center"> 图:重复排列剪枝 </p>
### 代码实现
### 2. &nbsp; 代码实现
在上一题的代码的基础上,我们考虑在每一轮选择中开启一个哈希表 `duplicated` ,用于记录该轮中已经尝试过的元素,并将重复元素剪枝。
@@ -905,7 +905,7 @@ comments: true
最大递归深度为 $n$ ,使用 $O(n)$ 栈帧空间。`selected` 使用 $O(n)$ 空间。同一时刻最多共有 $n$ 个 `duplicated` ,使用 $O(n^2)$ 空间。**因此空间复杂度为 $O(n^2)$** 。
### 两种剪枝对比
### 3. &nbsp; 两种剪枝对比
请注意,虽然 `selected` 和 `duplicated` 都用作剪枝,但两者的目标不同: