您的位置:首页 > 其它

字符串的全排列

2016-05-01 16:57 357 查看
字符串的全排列问题:

给定字符串S[0...N-1],设计算法,枚举字符串的全排列。

1、无重复字符串全排列非递归算法

程序实现:

//无重复字符串的全排列递归算法
void Permutaion(int* a,int size,int index){
if(index == size-1){
Print(a,size);
return;
}
for(int i=index;i<size;i++){
swap(a[i],a[index]);
Permutaion(a,size,index+1);
swap(a[i],a[index]);
}
}


运行结果:



说明:在每次递归前需要保证字符串的顺序不变,因此有每次的替换过程。

2、有重复字符串队规算法

程序实现:

//判断从a[to]是否与(index,to)重复
bool IsDuplicate(int* a,int index,int to){
while(index<to){
if(a[index]==a[to]){
return true;
}
index++;
}
return false;
}
//有重复字符串的全排列递归算法,Time Cost O((n+1)!)
void Permutaion1(int* a,int size,int index){
if(index == size-1){
Print(a,size);
return;
}
for(int i=index;i<size;i++){
if(!IsDuplicate(a,index,i)){
swap(a[i],a[index]);
Permutaion1(a,size,index+1);
swap(a[i],a[index]);
}
}
}


运行结果:



说明:本算法时间复杂度能达到O((n+1)!),不可取。

改进:利用空间换时间,采用下列的程序实现:

//有重复字符串的全排列递归算法,空间换时间
void Permutaion2(int* a,int size,int index){
if(index == size-1){
Print(a,size);
return;
}
int dup[256] = {0};
for(int i=index;i<size;i++){
if(dup[a[i]]==1)
continue;
dup[a[i]] = 1;
swap(a[i],a[index]);
Permutaion2(a,size,index+1);
swap(a[i],a[index]);
}
}


运行结果:



3、使用求下一个排列的思想,构造非递归算法。

过程:从当前排列生成字典序刚好比它大的下一个排列。

程序实现:

//字符串全排列非递归算法,求下一个排列的思想
void Reverse(int* from,int* to){
int t;
while(from<to){
t = *from;
*from = *to;
*to = t;
from++;
to --;
}
}
bool GetNextPermutation(int* a,int size){
//后找,从后向前找最后一个升序的位置
int i = size-2;
while((i>=0)&&(a[i]>=a[i+1]))
i--;
if(i<0) return false;
//查找,从后面的元素中寻找比a[i]大的最小值a[j]
int j=size-1;
while(a[j]<=a[i])
j--;
//交换
swap(a[i],a[j]);
//翻转 a[i+1...N-1]
Reverse(a+i+1,a+size-1);
return true;
}


运行结果:



说明:非递归算法天然解决重复字符问题。

另附上全部实现程序,仅供参考:

/***************************************
FileName StringPermutation.cpp
Author : godfrey
CreatedTime : 2016/5/1
****************************************/
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

void Print(const int* a,int size){
for(int i=0;i<size;i++){
cout<<a[i]<<' ';
}
cout<<endl;
}
//无重复字符串的全排列递归算法
void Permutaion(int* a,int size,int index){
if(index == size-1){
Print(a,size);
return;
}
for(int i=index;i<size;i++){
swap(a[i],a[index]);
Permutaion(a,size,index+1);
swap(a[i],a[index]);
}
}
//判断从a[to]是否与(index,to)重复
bool IsDuplicate(int* a,int index,int to){
while(index<to){
if(a[index]==a[to]){
return true;
}
index++;
}
return false;
}
//有重复字符串的全排列递归算法,Time Cost O((n+1)!)
void Permutaion1(int* a,int size,int index){
if(index == size-1){
Print(a,size);
return;
}
for(int i=index;i<size;i++){
if(!IsDuplicate(a,index,i)){
swap(a[i],a[index]);
Permutaion1(a,size,index+1);
swap(a[i],a[index]);
}
}
}
//有重复字符串的全排列递归算法,空间换时间
void Permutaion2(int* a,int size,int index){
if(index == size-1){
Print(a,size);
return;
}
int dup[256] = {0};
for(int i=index;i<size;i++){
if(dup[a[i]]==1)
continue;
dup[a[i]] = 1;
swap(a[i],a[index]);
Permutaion2(a,size,index+1);
swap(a[i],a[index]);
}
}
//字符串全排列非递归算法,求下一个排列的思想
void Reverse(int* from,int* to){
int t;
while(from<to){
t = *from;
*from = *to;
*to = t;
from++;
to --;
}
}
bool GetNextPermutation(int* a,int size){
//后找,从后向前找最后一个升序的位置
int i = size-2;
while((i>=0)&&(a[i]>=a[i+1]))
i--;
if(i<0) return false;
//查找,从后面的元素中寻找比a[i]大的最小值a[j]
int j=size-1;
while(a[j]<=a[i])
j--;
//交换
swap(a[i],a[j]);
//翻转 a[i+1...N-1]
Reverse(a+i+1,a+size-1);
return true;
}
int main()
{
int a[] = {1,2,3,4};
cout<<"-----无重复字符串全排列递归算法-------"<<endl;
Permutaion(a,sizeof(a)/sizeof(int),0);
int a1[] = {1,2,2,3};
cout<<"-----有重复字符串全排列递归算法-------"<<endl;
Permutaion1(a1,sizeof(a1)/sizeof(int),0);
cout<<"-----有重复字符串全排列递归算法(空间换时间)-------"<<endl;
Permutaion2(a1,sizeof(a1)/sizeof(int),0);
cout<<"-----字符串全排列非递归算法------------"<<endl;
int size = sizeof(a)/sizeof(int);
Print(a,size);
while(GetNextPermutation(a,size))
Print(a,size);
return 0;
}


转载请注明出处:

C++博客园:godfrey_88

http://www.cnblogs.com/gaobaoru-articles/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: