This commit is contained in:
krahets
2026-04-03 18:46:15 +08:00
parent 377736b1bd
commit 9d21ca86b0
352 changed files with 46563 additions and 11262 deletions
@@ -40,7 +40,7 @@ As shown in Figure 13-5, we can unfold the search process into a recursion tree,
To ensure that each element is chosen only once, we consider introducing a boolean array `selected`, where `selected[i]` indicates whether `choices[i]` has been chosen. We implement the following pruning operation based on it.
- After making a choice `choice[i]`, we set `selected[i]` to $\text{True}$, indicating that it has been chosen.
- After making a choice `choices[i]`, we set `selected[i]` to $\text{True}$, indicating that it has been chosen.
- When traversing the candidate list `choices`, we skip all nodes that have been chosen, which is pruning.
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. Then we need to prune the branch of element $1$ in the second round and prune the branches of elements $1$ and $3$ in the third round.
@@ -546,7 +546,7 @@ After understanding the above information, we can fill in the blanks in the temp
Suppose the input array is $[1, 1, 2]$. To distinguish the two duplicate elements $1$, we denote the second $1$ as $\hat{1}$.
As shown in Figure 13-7, the method described above generates permutations where half 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" }
@@ -554,7 +554,7 @@ As shown in Figure 13-7, the method described above generates permutations where
So how do we remove duplicate permutations? The most direct approach is to use a hash set to directly deduplicate the permutation results. However, this is not elegant because **the search branches that generate duplicate permutations are unnecessary and should be identified and pruned early**, which can further improve algorithm efficiency.
### 1.   Pruning Duplicate Elements
### 1.   Pruning Equal Elements
Observe Figure 13-8. In the first round, choosing $1$ or choosing $\hat{1}$ is equivalent. All permutations generated under these two choices are duplicates. Therefore, we should prune $\hat{1}$.
@@ -568,7 +568,7 @@ Essentially, **our goal is to ensure that multiple equal elements are chosen onl
### 2.   Code Implementation
Building on the code from the previous problem, we consider opening a hash set `duplicated` in each round of choices to record which elements have been tried in this round, and prune duplicate elements:
Building on the code from the previous problem, we initialize a hash set `duplicated` in each round of choices to record which elements have already been tried in that round, and prune equal elements:
=== "Python"
@@ -1089,7 +1089,7 @@ The maximum recursion depth is $n$, using $O(n)$ stack frame space. `selected` u
Note that although both `selected` and `duplicated` are used for pruning, they have different objectives.
- **Pruning duplicate choices**: There is only one `selected` throughout the entire search process. It records which elements are included in the current state, and its purpose is to prevent an element from appearing repeatedly in `state`.
- **Pruning duplicate elements**: Each round of choices (each `backtrack` function call) contains a `duplicated` set. It records which elements have been chosen in this round's iteration (the `for` loop), and its purpose is to ensure that equal elements are chosen only once.
- **Pruning equal elements**: Each round of choices (each `backtrack` function call) contains a `duplicated` set. It records which elements have been chosen in this round's iteration (the `for` loop), and its purpose is to ensure that equal elements are chosen only once.
Figure 13-9 shows the effective scope of the two pruning conditions. Note that each node in the tree represents a choice, and the nodes on the path from the root to a leaf node form a permutation.