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.递归搜索树
image

3.时间复杂度分析
image

代码:


#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;
}
posted @ 2024-04-12 20:49  HJfjfK  阅读(78)  评论(0编辑  收藏  举报