输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
剑指offer上的代码是用C写的,代码如下:
C Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
void
Permutation_(
char
*pStr,
char
*pBegin) { if (*pBegin == '\0' ) cout << pStr << endl; else { for ( char *pCh = pBegin; *pCh != '\0' ; ++pCh) { char temp = *pCh; *pCh = *pBegin; *pBegin = temp; Permutation_(pStr, pBegin + 1 ); temp = *pCh; *pCh = *pBegin; *pBegin = temp; } } } void Permutation_( char *pStr) { if (pStr == NULL ) return ; Permutation_(pStr, pStr); } void main() { char str[] = "aa" ; Permutation_(str); return ; } |
但是这个代码有个问题就是当字符串中有重复的字母出现的时候,打印出的全排列也会有重复,例如:
输入的字符串是“aa"的时候,输出为:aa aa,其正确输出应该为:aa
输入为aab的时候,输出为:aab aba aab aba baa baa 其正确输出应该为:aab aba baa
先给出C++的代码,并去除了结果中重复的字符串,代码如下:
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
void
Permutation( string &pBegin,
int
n, vector<string> &res)//n为下标值 { int size = pBegin.size(); if (n == size) res.push_back(pBegin);//如果下标值等于字符串的长度,输出字符串 else { for ( int i = n; i < pBegin.size(); i++) { char temp = pBegin[i]; pBegin[i] = pBegin[n]; pBegin[n] = temp; Permutation(pBegin, n + 1 , res);//移动下标 temp = pBegin[i]; pBegin[i] = pBegin[n]; pBegin[n] = temp; } } } vector<string> Permutation(string pStr) { vector<string> res; if (pStr.size() == 0 ) return res; Permutation(pStr, 0 , res); sort(res.begin(), res.end()); //使用unique的使用,要先排序 res.erase(unique(res.begin(), res.end()), res.end()); //unique去重 //unique()函数将重复的元素放到vector的尾部 然后返回指向第一个重复元素的迭代器 再用erase函数擦除从这个元素到最后元素的所有的元素 return res; } void main() { char str[] = "aab" ; vector<string> res = Permutation(str); return ; } |
输出正确的结果。