字符串的全排列

字符串的全排列问题:

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

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

程序实现:

 1 //无重复字符串的全排列递归算法
 2 void Permutaion(int* a,int size,int index){
 3     if(index == size-1){
 4         Print(a,size);
 5         return;
 6     }
 7     for(int i=index;i<size;i++){
 8         swap(a[i],a[index]);
 9         Permutaion(a,size,index+1);
10         swap(a[i],a[index]);
11     }
12 }

运行结果:

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

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

程序实现:

 1 //判断从a[to]是否与(index,to)重复
 2 bool IsDuplicate(int* a,int index,int to){
 3     while(index<to){
 4         if(a[index]==a[to]){
 5             return true;
 6         }
 7         index++;
 8     }
 9     return false;
10 }
11 //有重复字符串的全排列递归算法,Time Cost O((n+1)!)
12 void Permutaion1(int* a,int size,int index){
13     if(index == size-1){
14         Print(a,size);
15         return;
16     }
17     for(int i=index;i<size;i++){
18         if(!IsDuplicate(a,index,i)){
19             swap(a[i],a[index]);
20             Permutaion1(a,size,index+1);
21             swap(a[i],a[index]);
22         }
23     }
24 }

运行结果:

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

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

 1 //有重复字符串的全排列递归算法,空间换时间
 2 void Permutaion2(int* a,int size,int index){
 3     if(index == size-1){
 4         Print(a,size);
 5         return;
 6     }
 7     int dup[256] = {0};
 8     for(int i=index;i<size;i++){
 9         if(dup[a[i]]==1)
10             continue;
11         dup[a[i]] = 1;
12         swap(a[i],a[index]);
13         Permutaion2(a,size,index+1);
14         swap(a[i],a[index]);
15     }
16 }

运行结果:

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

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

程序实现:

 1 //字符串全排列非递归算法,求下一个排列的思想
 2 void Reverse(int* from,int* to){
 3     int t;
 4     while(from<to){
 5         t = *from;
 6         *from = *to;
 7         *to = t;
 8         from++;
 9         to --;
10     }
11 }
12 bool GetNextPermutation(int* a,int size){
13     //后找,从后向前找最后一个升序的位置
14     int i = size-2;
15     while((i>=0)&&(a[i]>=a[i+1]))
16         i--;
17     if(i<0) return false;
18     //查找,从后面的元素中寻找比a[i]大的最小值a[j]
19     int j=size-1;
20     while(a[j]<=a[i])
21         j--;
22     //交换
23     swap(a[i],a[j]);
24     //翻转 a[i+1...N-1]
25     Reverse(a+i+1,a+size-1);
26     return true;
27 }

运行结果:

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

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

  1 /***************************************
  2 FileName StringPermutation.cpp
  3 Author : godfrey
  4 CreatedTime : 2016/5/1
  5 ****************************************/
  6 #include <iostream>
  7 #include <cstring>
  8 #include <vector>
  9 #include <algorithm>
 10 #include <stdio.h>
 11 #include <stdlib.h>
 12 
 13 using namespace std;
 14 
 15 void Print(const int* a,int size){
 16     for(int i=0;i<size;i++){
 17         cout<<a[i]<<' ';
 18     }
 19     cout<<endl;
 20 }
 21 //无重复字符串的全排列递归算法
 22 void Permutaion(int* a,int size,int index){
 23     if(index == size-1){
 24         Print(a,size);
 25         return;
 26     }
 27     for(int i=index;i<size;i++){
 28         swap(a[i],a[index]);
 29         Permutaion(a,size,index+1);
 30         swap(a[i],a[index]);
 31     }
 32 }
 33 //判断从a[to]是否与(index,to)重复
 34 bool IsDuplicate(int* a,int index,int to){
 35     while(index<to){
 36         if(a[index]==a[to]){
 37             return true;
 38         }
 39         index++;
 40     }
 41     return false;
 42 }
 43 //有重复字符串的全排列递归算法,Time Cost O((n+1)!)
 44 void Permutaion1(int* a,int size,int index){
 45     if(index == size-1){
 46         Print(a,size);
 47         return;
 48     }
 49     for(int i=index;i<size;i++){
 50         if(!IsDuplicate(a,index,i)){
 51             swap(a[i],a[index]);
 52             Permutaion1(a,size,index+1);
 53             swap(a[i],a[index]);
 54         }
 55     }
 56 }
 57 //有重复字符串的全排列递归算法,空间换时间
 58 void Permutaion2(int* a,int size,int index){
 59     if(index == size-1){
 60         Print(a,size);
 61         return;
 62     }
 63     int dup[256] = {0};
 64     for(int i=index;i<size;i++){
 65         if(dup[a[i]]==1)
 66             continue;
 67         dup[a[i]] = 1;
 68         swap(a[i],a[index]);
 69         Permutaion2(a,size,index+1);
 70         swap(a[i],a[index]);
 71     }
 72 }
 73 //字符串全排列非递归算法,求下一个排列的思想
 74 void Reverse(int* from,int* to){
 75     int t;
 76     while(from<to){
 77         t = *from;
 78         *from = *to;
 79         *to = t;
 80         from++;
 81         to --;
 82     }
 83 }
 84 bool GetNextPermutation(int* a,int size){
 85     //后找,从后向前找最后一个升序的位置
 86     int i = size-2;
 87     while((i>=0)&&(a[i]>=a[i+1]))
 88         i--;
 89     if(i<0) return false;
 90     //查找,从后面的元素中寻找比a[i]大的最小值a[j]
 91     int j=size-1;
 92     while(a[j]<=a[i])
 93         j--;
 94     //交换
 95     swap(a[i],a[j]);
 96     //翻转 a[i+1...N-1]
 97     Reverse(a+i+1,a+size-1);
 98     return true;
 99 }
100 int main()
101 {
102     int a[] = {1,2,3,4};
103     cout<<"-----无重复字符串全排列递归算法-------"<<endl;
104     Permutaion(a,sizeof(a)/sizeof(int),0);
105     int a1[] = {1,2,2,3};
106     cout<<"-----有重复字符串全排列递归算法-------"<<endl;
107     Permutaion1(a1,sizeof(a1)/sizeof(int),0);
108     cout<<"-----有重复字符串全排列递归算法(空间换时间)-------"<<endl;
109     Permutaion2(a1,sizeof(a1)/sizeof(int),0);
110     cout<<"-----字符串全排列非递归算法------------"<<endl;
111     int size = sizeof(a)/sizeof(int);
112     Print(a,size);
113     while(GetNextPermutation(a,size))
114         Print(a,size);
115     return 0;
116 }

转载请注明出处:

C++博客园:godfrey_88

http://www.cnblogs.com/gaobaoru-articles/

转载请注明出处: C++博客园:godfrey_88 http://www.cnblogs.com/gaobaoru-articles/
原文地址:https://www.cnblogs.com/gaobaoru-articles/p/5450763.html