前段时间面试了一家公司的图像岗位,居然尽问我C++的知识,还让我写全排列,表示无语……,不过还是硬着头皮写了下,这么久没接触算法,之前也没写过全排列,汗颜呀,回来还发现写法有些low,贴出当时的代码,mark下学业不精的尴尬,顺便熟悉一下MarkDown,以后再也不用Word写博客了,
题目
输出 1,2,…,N的全排列
样例
基本思路是DFS,考虑到递归的栈消耗,于是用数组来实现非递归,时间复杂度为
N!
,上代码:
- flag: 是否已经选中的标记,已经选择了为1,否则为0
- state: 记录上一次搜索到的数字
- data: 存放全排列
#include"iostream"
#include <iomanip>
using namespace std;
void fullPerm(int N)
{
int *flag=new int [N];
int *state=new int[N];
int *data = new int[N];
memset(flag,0,sizeof(int)*N);
memset(state, 0, sizeof(int)*N);
int d = 0;
int cnt = 1;
while (true)
{
if (N == d)//到底了
{
cout <<setw(3)<<cnt++<<": ";
for (int i = 0; i < N; i++)
cout << data[i]+1 << " ";
cout << endl;
d--;//回溯
flag[state[d]] = 0;//上去的时候释放选中的元素
state[d]++;
}
else
{
int s = state[d];
for (; s < N; s++)//寻找下一个没有被选中的元素
{
if (0 == flag[s])//往下搜索
{
data[d] = s;
flag[s] = 1;//下来的时候选择元素
state[d] = s;
d++;
break;
}
}
if (s == N)//中间层回溯
{
state[d] = 0;
d--;
if (d < 0)//回溯到了最顶层
break;
flag[state[d]] = 0;
state[d]++;
}
}
}
delete[] flag;
delete[] state;
delete[] data;
}
void main(void)
{
int n;
cin >> n;
fullPerm(n);
system("pause");
}