全排列

进阶

全排列展示了回溯里"做选择、递归、撤销选择"的完整节奏。

全排列

枚举所有排列,观察回溯的「选择-递归-撤销」节奏。

AlgoAnim · 全排列

待机

速度
待机
// 源代码
1vector<int> path;
2vector<int> used;
3
4void dfs(const vector<int>& nums) {
5    if (path.size() == nums.size()) {
6        return;
7    }
8    for (int i = 0; i < (int)nums.size(); i++) {
9        if (used[i]) continue;
10        used[i] = 1;
11        path.push_back(nums[i]);
12        dfs(nums);
13        path.pop_back();
14        used[i] = 0;
15    }
16}

复杂度分析

时间 O(n * n!)
空间 O(n)
最优 O(1)
最坏 O(n * n!)

算法讲解

全排列的目标是枚举所有可能顺序,因此每一层递归都要决定当前位置放哪个还没用过的数。

回溯模板的关键就在于:选择一个候选,进入下一层,返回后把现场恢复。

如果这个"恢复现场"的动作漏掉了,后续分支就会带着脏状态继续跑,结果通常全错。

很多搜索题本质都可以看作"在状态树上枚举一条合法路径"。