全排列的遞歸定義:設集合 R = {r₁, r₂, ..., rₙ},Rᵢ = R - {rᵢ}。則 Perm(R) = (r₁) + Perm(R₁) ∪ (r₂) + Perm(R₂) ∪ ... ∪ (rₙ) + Perm(Rₙ)。基例 n=1 時 Perm(R) = (r)。
以 {1,2,3} 為例,進入遞歸處理 {2,3}:
每次交換後遞歸,返回時必須交換回原狀,確保同層後續迭代的正確性。這是回溯法的核心:做選擇 → 遞歸 → 撤銷選擇。
#include
using namespace std;
void swap(int &a, int &b) { int t = a; a = b; b = t; }
void perm(int list[], int low, int high) {
if (low == high) {
for (int i = 0; i <= high; i++) cout << list[i];
cout << " ";
return;
}
for (int i = low; i <= high; i++) {
swap(list[low], list[i]); // 做選擇
perm(list, low + 1, high); // 遞歸
swap(list[low], list[i]); // 撤銷選擇
}
}
int main() {
int a[] = {1, 2, 3};
perm(a, 0, 2);
return 0;
}
// 輸出:123 132 213 231 321 312
O(n!),輸出所有排列的理論下界。O(n),遞歸棧深度。std::next_permutation 實現非遞歸字典序生成。全排列遞歸是回溯法的教科書級範例。通過交換元素固定前綴、遞歸處理剩餘、回溯恢復狀態,優雅地解決了排列生成問題。理解其「選擇-遞歸-撤銷」三部曲,對掌握 DFS/回溯算法至關重要。