您的位置:首页 > 其它

【万能搜索】万能DFS之全排列(一)——普通算法

2017-12-03 13:53 253 查看
DFS相信大家都很熟悉,下面就给出一种用DFS实现的算法。

全排列

大家对于全排列是很熟悉的,比如123的全排列就有:

123

132

213

231

312

321

这六种。

现在,我们来设计一个算法,来求出所有全排列。

一个暴力算法

在全排列中,我们只需不停地试每一个元素所在的位置,再根据全排列中同一元素只出现一次,就可以暴力枚举出全排列。

//暴力实现
bool check(int x,int i)
{
for(int k=1;k<=x;k++)
if(ans[k]==a[x])return 0;
return 1;
}
void dfs(int x)
{
if(x>n)
{
Print();//输出
return;//千万不要打掉这句
//不打会将一个排列输出两次
}
for(int i=1;i<=n;i++)//n是长度
if(check(x,i))
{
ans[x]=a[i];
dfs(x+1);
}
}


不难看出,这个算法时间复杂度为O(n2×n!)O(n2×n!)。非常慢。

暴力算法v2.0

其实我们可以仔细想想,在ans数组中,每个元素只对应原数组的唯一一个位置,所以,我们就可以利用这一性质,用O(1)O(1)的时间来找出值。

//暴力实现v2.0
void dfs(int x)
{
if(x>n)
{
Print();
return;
}
for(int i=1;i<=n;i++)
if(!bo[i])
{
ans[x]=a[i];
bo[i]=1;
dfs(x+1);
bo[i]=0;//不打这句你会死得很惨
}
}


这个算法时间复杂度也比较慢,为O(n×n!)O(n×n!)。

一个看上去很NB的算法

先给代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int a[101],n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
sort(a+1,a+n+1);
do Print();
while(next_permutation(a+1,a+n+1));
return 0;
}


是很NB吧,还自带字典序输出。没错,这就是万能的algorithm库里面的next_permutation函数!它能在O(n!)O(n!)的时间复杂度求出所有全排列!这是已知的、最快的求出全排列的方法。还可以处理重复元素!

关于这个算法的实现方法,我们下节再论。

搜索系列文章:

1. 【未完】【万能搜索】万能DFS之全排列(二)——next_permutation详解

2. 【未完】【万能搜索】万能BFS之最短路(一)——走迷宫

3. 【未完】【万能搜索】万能BFS之最短路(二)——详解八数码问题
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dfs 算法