题目描述
按照字典序输出自然数 1 到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入格式
一个整数 n。
输出格式
由 1∼n 组成的所有不重复的数字序列,每行一个序列。
每个数字保留 5 个场宽。
输入输出样例
输入 #1
3
输出 #1
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
说明/提示
1≤n≤9。
解题思路
问题分析
全排列问题是一个经典的递归问题。我们需要生成 1 到 n 的所有排列,且每个排列中的数字不能重复。为了实现这一点,可以使用深度优先搜索(DFS)算法,通过回溯法逐步构建排列。
思路解析
- **DFS(深度优先搜索)**:
-
使用 DFS 逐步构建排列,每次选择一个未使用的数字加入当前排列。
-
当排列的长度 n达到 时,输出该排列。
- **回溯法**:
-
在每次递归调用中,标记当前选择的数字为已使用(`hx[i] = 1`)。
-
递归完成后,回溯并取消标记(`hx[i] = 0`),以便尝试其他可能的排列。
- **标记数组**:
- 使用一个标记数组 `hx` 来记录每个数字是否已经被使用,避免重复选择。
算法步骤
-
初始化一个标记数组 `hx`,用于记录每个数字是否被使用。
-
定义一个递归函数 `dfs(x)`,其中 `x` 表示当前排列的长度。
-
在递归函数中:
-
如果 `x` 等于 n,说明已经生成了一个完整的排列,输出该排列。
-
否则,遍历所有可能的数字(1 到 n),选择未使用的数字加入当前排列,并递归调用 `dfs(x+1)`。
-
递归返回后,取消标记,以便尝试其他数字。
代码实现
cpp
#include<bits/stdc++.h>
using namespace std;
int n;
int d[15]={0};
int hx[15]={0};
void dfs(int x)
{
if(x == n) //可以输出
{
for(int i=0;i<n;++i)
printf("%5d",d[i]);
printf("\n");
}
for(int i=0;i<n;++i)
{
if(hx[i] == 0)
{
hx[i] = 1;
d[x] = i + 1;
dfs(x+1);
hx[i] = 0;
}
}
}
int main()
{
cin>>n;
dfs(0);
return 0;
}
总结
这道题目是一个典型的全排列问题,使用 DFS 和回溯法可以高效地生成所有排列。通过标记数组避免重复选择数字,确保生成的排列符合要求。DFS 的递归结构清晰,适合解决类似的问题。