C++算法题解 - 递归实现排列型枚举 - 递归法 (图文) (递归搜索树)
题目:递归实现排列型枚举
把 1∼n这n个整数排成一行后随机打乱顺序,输出所有可能的次序。
输入格式
一个整数n。
输出格式
按照从小到大的顺序输出所有方案,每行 1个。
首先,同一行相邻两个数用一个空格隔开。
其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。
数据范围
1≤n≤9
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
题解:
1.方法
方法1: 第一个数放到哪个位置. 例如n==3时, 1放到第一个坑还是第二个坑还是第三个坑.然后再放2...
方法2: 第一个坑放哪个数,第二个坑放哪个数, ...
两种方法实际都一样,仅出发点不同.本题解是方法2.
2.字典序最小
第一个节点开始,先选择最小的,即选择1,之后再次回到第一个节点选择时,
选择最小的,即选择2.而2一定大于1,即符合字典序最小.依次下去,第一个节点的结果一定是符合字典序最小.
递归下去,之后的每个节点一定也符合根节点满足字典序最小的情况.
3.递归搜索树
3.时间复杂度分析
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
//知道范围后可以开一个很大的全局数组,之后就可以不用传参,方便递归
const int N = 10;
int state[N]; //记录选过的数字
bool used[N]; //false表示未使用过,true表示已使用当前下标的数字
int n; //题目传入参数
void dfs(int u)
{
if(u>n)
{
for(int i = 1; i <= n; i++) //遍历state数组 输出结果
{
printf("%d ",state[i]);
}
puts("");
return ;
}
for(int i = 1; i<=n; i++) //遍历used数组(分支) 寻找未使用过的数字, 并使用该数字
{
if(used[i] == false)
{
used[i] = true;
state[u] = i;
dfs(u+1);
//递归回来后恢复现场
used[i] = false;
state[u] = 0;
}
}
}
int main()
{
scanf("%d",&n);
dfs(1); //从1开始,与层数对应: 1==第一层
return 0;
}
本文来自博客园,作者:HJfjfK,原文链接:https://www.cnblogs.com/DSCL-ing/p/18132065