mirror of
https://github.com/krahets/hello-algo.git
synced 2025-12-19 07:17:54 +08:00
Add subtitles to docs
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
## 无重复的情况
|
||||
## 无相等元素的情况
|
||||
|
||||
!!! question
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||

|
||||
|
||||
### 代码实现
|
||||
|
||||
想清楚以上信息之后,我们就可以在框架代码中做“完形填空”了。为了缩短代码行数,我们不单独实现框架代码中的各个函数,而是将他们展开在 `backtrack()` 函数中。
|
||||
|
||||
=== "Java"
|
||||
@@ -118,13 +120,15 @@
|
||||
[class]{}-[func]{permutationsI}
|
||||
```
|
||||
|
||||
### 重复选择剪枝
|
||||
|
||||
需要重点关注的是,我们引入了一个布尔型数组 `selected` ,它的长度与输入数组长度相等,其中 `selected[i]` 表示 `choices[i]` 是否已被选择。我们利用 `selected` 避免某个元素被重复选择,从而实现剪枝。
|
||||
|
||||
如下图所示,假设我们第一轮选择 1 ,第二轮选择 3 ,第三轮选择 2 ,则需要在第二轮剪掉元素 1 的分支,在第三轮剪掉元素 1, 3 的分支。**此剪枝操作可将搜索空间大小从 $O(n^n)$ 降低至 $O(n!)$** 。
|
||||
|
||||

|
||||
|
||||
## 考虑重复的情况
|
||||
## 考虑相等元素的情况
|
||||
|
||||
!!! question
|
||||
|
||||
@@ -138,9 +142,13 @@
|
||||
|
||||
观察发现,在第一轮中,选择 $1$ 或选择 $\hat{1}$ 是等价的,因为在这两个选择之下生成的所有排列都是重复的。因此,我们应该把 $\hat{1}$ 剪枝掉。同理,在第一轮选择 $2$ 后,第二轮选择中的 $1$ 和 $\hat{1}$ 也会产生重复分支,因此也需要将第二轮的 $\hat{1}$ 剪枝。
|
||||
|
||||
本质上看,**我们的目标是实现在某一轮选择中,多个相等的元素仅被选择一次**。
|
||||
|
||||

|
||||
|
||||
本质上看,**我们的目标是实现在某一轮选择中,多个相等的元素仅被选择一次**。因此,在上一题的代码的基础上,我们考虑在每一轮选择中开启一个哈希表 `duplicated` ,用于记录该轮中已经尝试过的元素,并将重复元素剪枝。
|
||||
### 代码实现
|
||||
|
||||
在上一题的代码的基础上,我们考虑在每一轮选择中开启一个哈希表 `duplicated` ,用于记录该轮中已经尝试过的元素,并将重复元素剪枝。
|
||||
|
||||
=== "Java"
|
||||
|
||||
@@ -230,6 +238,8 @@
|
||||
[class]{}-[func]{permutationsII}
|
||||
```
|
||||
|
||||
### 两种剪枝对比
|
||||
|
||||
注意,虽然 `selected` 和 `duplicated` 都起到剪枝的作用,但他们剪掉的是不同的分支:
|
||||
|
||||
- **剪枝条件一**:整个搜索过程中只有一个 `selected` 。它记录的是当前状态中包含哪些元素,作用是避免某个元素在 `state` 中重复出现。
|
||||
@@ -239,7 +249,7 @@
|
||||
|
||||

|
||||
|
||||
## 复杂度分析
|
||||
### 复杂度分析
|
||||
|
||||
假设元素两两之间互不相同,则 $n$ 个元素共有 $n!$ 种排列(阶乘);在记录结果时,需要复制长度为 $n$ 的列表,使用 $O(n)$ 时间。因此,**时间复杂度为 $O(n!n)$** 。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user