题目描述:
设计一个递归算法,求n个不同字符的所有排列
参考答案算法思想
上图为参考答案给出的算法,其核心思想在于交换,例如让A和字符串中的每一个字符都进行交换(包括A与自身交换,也可以描述为不交换)得到ABC、BAC、CBA这三种排列,即树中第二层,将第二层的第一个结点视为落在最终位置,从第二个结点开始,重复上述交换过程…最终输出叶子结点即为全排列。
算法改进:
不难发现这其中的交换操作是可以省略的,通过构造哈希数组(即用于标记字符串当前位是否加入全排列,初始值全为false),当字符串的某一号位加入全排列时,将哈希数组值修改为true,当递归完成时,将其还原为false以便将下一个字符加入全排列,下面给出完整代码
#include<iostream>
#include<cstring>
using namespace std;
char p[11]; //存储全排列信息
bool hashtable[11] = {false}; //标记当前位
//输出长度为n的字符串的全排列,从index开始
void generativeP(char s[],int index, int n) {
//递归边界, 输出当前排列
if(index == n) {//已经处理完n号位
cout<<p<<endl;
return; //返回上一层递归出口
}
//枚举字符串s的0-n-1位,试图将s[x]填入p[index]
for(int x = 0; x < n; x++) {
if(hashtable[x] == false) { //当前字符未排列
p[index] = s[x]; //字符串的第x位加入排列
hashtable[x] = true; //标记字符串的第x位已加入排列
generativeP(s, index+1, n);//处理第index+1号位
hashtable[x] = false;//已处理完p[index]为s[x]子问题
}
}
}
int main(){
char s[] = "ABCD";
// cin>>s;
generativeP(s, 0, strlen(s)); //从字符串首位开始排列
return 0;
}