题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。
思路:
求整个字符串的排列,可以分为两步:
第一步:求所有可能出现在第一个位置的字符(即把第一个字符和后面所有的字符交换);
第二步:固定第一个字符,求后面所有字符的排列(即仍把后面的所有字符分为两部分:后面字符的第一个字符,以及这个字符之后的所有字符)。
核心代码如下:
解法一:未避免重复字符
void Permutation(char* pStr, char* pBegin);
void Permutation(char* pStr){
if(pStr == nullptr)
return;
Permutation(pStr, pStr);
}
//pStr指向整个字符串的第一个字符
//pBegin指向当前执行排列操作的字符串的第一个字符
void Permutation(char* pStr, char* pBegin){
if(*pBegin == '\0'){
cout << pStr << endl;
}else{
for(char* pCh = pBegin; *pCh != '\0'; pCh++){ //以abc为例,分别为:a与a交换->abc;a与b交换->bac; a与c交换->cba
char temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
//对pBegin后面的字符串递归进行排列操作
Permutation(pStr, pBegin + 1);
//恢复原字符串,以供第一个字符与后续的pCh++字符继续交换
temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
}
}
}
解法二:避免重复字符
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> result; //创建一个字符数组
int length = str.size();
if(length == 0) //当字符串为空时,直接返回结果
return result;
Permutations(result, str, 0, length);
return result;
}
void Permutations(vector<string>&result, string str, int index, int len){
if(index == len){ //当递归到最后一位字符时,排列结束,输出该字符数组
result.push_back(str);
return;
}
for(int i = index; i < len; i++){
if(i != index && str[i] == str[index]) //保证当输入多个重复字符时,不会重复计算
continue;
swap(str[i], str[index]); //交换两个字符
Permutations(result, str, index + 1, len); //继续递归
}
}
};