This commit is contained in:
krahets
2024-05-01 07:30:10 +08:00
parent 583d338530
commit a08cd961b3
64 changed files with 227 additions and 227 deletions
@@ -6,13 +6,13 @@ comments: true
The permutation problem is a typical application of the backtracking algorithm. It is defined as finding all possible arrangements of elements from a given set (such as an array or string).
The Table 13-2 lists several example data, including the input arrays and their corresponding permutations.
Table 13-2 lists several example data, including the input arrays and their corresponding permutations.
<p align="center"> Table 13-2 &nbsp; Permutation examples </p>
<div class="center-table" markdown>
| Input array | Permutations |
| Input array | Permutations |
| :---------- | :----------------------------------------------------------------- |
| $[1]$ | $[1]$ |
| $[1, 2]$ | $[1, 2], [2, 1]$ |
@@ -30,7 +30,7 @@ From the perspective of the backtracking algorithm, **we can imagine the process
From the code perspective, the candidate set `choices` contains all elements of the input array, and the state `state` contains elements that have been selected so far. Please note that each element can only be chosen once, **thus all elements in `state` must be unique**.
As shown in the following figure, we can unfold the search process into a recursive tree, where each node represents the current state `state`. Starting from the root node, after three rounds of choices, we reach the leaf nodes, each corresponding to a permutation.
As shown in Figure 13-5, we can unfold the search process into a recursive tree, where each node represents the current state `state`. Starting from the root node, after three rounds of choices, we reach the leaf nodes, each corresponding to a permutation.
![Permutation recursive tree](permutations_problem.assets/permutations_i.png){ class="animation-figure" }
@@ -43,13 +43,13 @@ To ensure that each element is selected only once, we consider introducing a boo
- After making the choice `choice[i]`, we set `selected[i]` to $\text{True}$, indicating it has been chosen.
- When iterating through the choice list `choices`, skip all nodes that have already been selected, i.e., prune.
As shown in the following figure, suppose we choose 1 in the first round, 3 in the second round, and 2 in the third round, we need to prune the branch of element 1 in the second round and elements 1 and 3 in the third round.
As shown in Figure 13-6, suppose we choose 1 in the first round, 3 in the second round, and 2 in the third round, we need to prune the branch of element 1 in the second round and elements 1 and 3 in the third round.
![Permutation pruning example](permutations_problem.assets/permutations_i_pruning.png){ class="animation-figure" }
<p align="center"> Figure 13-6 &nbsp; Permutation pruning example </p>
Observing the above figure, this pruning operation reduces the search space size from $O(n^n)$ to $O(n!)$.
Observing Figure 13-6, this pruning operation reduces the search space size from $O(n^n)$ to $O(n!)$.
### 2. &nbsp; Code implementation
@@ -532,7 +532,7 @@ After understanding the above information, we can "fill in the blanks" in the fr
Suppose the input array is $[1, 1, 2]$. To differentiate the two duplicate elements $1$, we mark the second $1$ as $\hat{1}$.
As shown in the following figure, half of the permutations generated by the above method are duplicates.
As shown in Figure 13-7, half of the permutations generated by the above method are duplicates.
![Duplicate permutations](permutations_problem.assets/permutations_ii.png){ class="animation-figure" }
@@ -542,7 +542,7 @@ So, how do we eliminate duplicate permutations? Most directly, consider using a
### 1. &nbsp; Pruning of equal elements
Observing the following figure, in the first round, choosing $1$ or $\hat{1}$ results in identical permutations under both choices, thus we should prune $\hat{1}$.
Observing Figure 13-8, in the first round, choosing $1$ or $\hat{1}$ results in identical permutations under both choices, thus we should prune $\hat{1}$.
Similarly, after choosing $2$ in the first round, choosing $1$ and $\hat{1}$ in the second round also produces duplicate branches, so we should also prune $\hat{1}$ in the second round.
@@ -1061,7 +1061,7 @@ Please note, although both `selected` and `duplicated` are used for pruning, the
- **Repeated choice pruning**: There is only one `selected` throughout the search process. It records which elements are currently in the state, aiming to prevent an element from appearing repeatedly in `state`.
- **Equal element pruning**: Each round of choices (each call to the `backtrack` function) contains a `duplicated`. It records which elements have been chosen in the current traversal (`for` loop), aiming to ensure equal elements are selected only once.
The following figure shows the scope of the two pruning conditions. Note, each node in the tree represents a choice, and the nodes from the root to the leaf form a permutation.
Figure 13-9 shows the scope of the two pruning conditions. Note, each node in the tree represents a choice, and the nodes from the root to the leaf form a permutation.
![Scope of the two pruning conditions](permutations_problem.assets/permutations_ii_pruning_summary.png){ class="animation-figure" }