打印字符串的全排列
算法的思路:
把一个字符串分成两部分,第一个字符+后面部分所有的字符。这样就能够递归的求解整个过程了:
1.每个字符都做一次首字符 2.当某个字符作为首字符的时候,求后面所有字符的全排列 而这里的求后面所有字符的全排列可以看成递归的子问题
全排列的递归树:
但是这里还有一个问题,那就是字符串中有重复的字符时,这样的算法会增加最后的结果数目。比如说字符串aab,a+ab的全排列,然后交换还是a+ab的全排列。所以会增加结果的数目。解决方案就是:当遇到重复的字符的时候就跳过去,不在进行递归。
所以代码实现:
#include <iostream> #include <algorithm> using namespace std; void getPermutation(char *pStr, char *pBegin); void Permutation(char *pStr); void Permutation(char *pStr) { if (pStr == NULL) { return; } getPermutation(pStr, pStr); } void getPermutation(char *pStr, char *pBegin) { if (*pBegin == ‘\0‘) { printf("%s\n", pStr); } else { for (char *pCh = pBegin; *pCh != ‘\0‘; ++pCh) { //如果是相同的字符,那么就不用在递归,防止产生多余的字符串结果 if (*pCh == *pBegin && pCh != pBegin) continue; swap(*pCh, *pBegin); getPermutation(pStr, pBegin + 1); swap(*pCh, *pBegin); } } }//getPermutation int main() { char str[] = "aab"; //这里实参如果是char *str = "abc";是不可行的,因为常量字符串是不能交换的 Permutation(str); return 0; }
这是C语言版的实现,再看C++版本的实现:
vector<string> Permutation(string str) { vector<string> res; if(str.size() == 0) return res; getPermutation(res, str, 0); sort(res.begin(), res.end()); return res; } void getPermutation(vector<string>& res, string& str, int begin) { if(begin == str.size()) { res.push_back(str); } else { for(unsigned int i = begin; i < str.size(); i++) { if(str[i] == str[begin] && i != begin) continue; swap(str[i], str[begin]); getPermutation(res, str, begin + 1); swap(str[i], str[begin]); }//for } }//getPermutation
时间: 2024-12-24 01:51:03