一、题目
按字典序生成1~n的全排列
二、解题思路
我们尝试用递归的思想解决: 先输出所有以1开头的排列( 这一步是递归调用) , 然后输出以2开头的排列( 又是递归调用) , 接着是以3开头的排列……最后才是以n 开头的排列。
以1开头的排列的特点是: 第一位是1, 后面是2~n的排列。 根据字典序的定义, 这些2~n的排列也必须按照字典序排列。 换句话说, 需要“按照字典序输出2~n的排列”, 不过需注意的是, 在输出时, 每个排列的最前面要加上“1”。 这样一来, 所设计的递归函数需要以下参数:
- 已经确定的“前缀”序列。
- 元素的标记数组,标记出已使用元素和未使用元素,从未使用的数组选出元素,加入前缀数组。
这样可以得到一个伪代码:
void dfs(容器A, 标记数组S)
{
if(容器A中的元素个数为N){
输出容器A中的元素;
}
//按照从小到大的顺序依次考虑S的未使用的元素v
else
{
dfs(在A的末尾填加v后得到的新序列, S-{v});
}
}
三、代码编写
#include <iostream>
#include <vector>
#define N 5
using namespace std;
//需要全排列的数组,必须按递增顺序
int a[N] = {-1,1,2,3,4};
//输出一个排列
void print(vector<int> vec){
vector<int>::iterator it = vec.begin();
for(it ; it != vec.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
//递归生成全排列
void dfs(vector<int>& vec,bool flag[]){
if(vec.size() == N-1){
print(vec);
}
else{
for(int i=1;i<N;i++){
//如果没有访问,则访问
if(flag[i] == false){
//将元素加入vector容器中
vec.push_back(a[i]);
//标记已访问
flag[i] = true;
//继续递归
dfs(vec,flag);
//回溯
vec.pop_back();
flag[i] = false;
}
}
}
}
int main()
{
bool flag[N] = {false};
vector<int> vec;
dfs(vec,flag);
return 0;
}
四、运行结果