(1)字符串全排列 / 组合
2013-11-01 20:13
288 查看
题目描述:输入一个字符串,打印出该字符串的全部排列;
例如:字符串:abc 全排列:(abc , acb) , (bac , bca) , (cba , cab);
解题思路:
递归实现:从字符串中“依次”选择一个字符作为“首字符”,并在该“首字符”前提下,对剩余字符进行递归全排列处理;
“依次”:即始终在“初始字符串”的前提下,后面的字符分别于第一个字符交换;
字符串abc:
(abc)首字符a-->求剩余bc全排列:abc , acb;-->(a,b)交换-->bac;
(bac)首字符b-->求剩余ac全排列:bac , bca;-->(a,b)交换-->abc(以便在此基础上得到cba)-->(a,c)交换-->cba;
(cba)首字符c-->求剩余ba全排列:cba,cab;
算法递归实现:
但是若字符串中出现重复的字符,两者交换。全排列中会出现重复的结果。这样不仅加大工作量,而且还是没有意义的,故应该去掉重复的全排列结果。
怎么去除呢?
规则:从首字符起,每个字符依次与后面不重复的字符交换。
例子:字符串abb;
(abb)首字符a-->求剩余全排列:abb-->(b,b)相等不交换;-->(a,b)交换bab;
(bab)首字符b-->求剩余全排列:bab , bba;-->(b,a)交换abb-->由于二三字符b ,b 相同,故a不再与第三个字符交换,结束;
代码实现:
字符串的组合问题:
问题描述:给定一个字符串,求该字符串中所有字符的组合;例如abc,所求组合为:a , b , c , ab , ac , bc , abc;
长度为n的字符串,选取m个字符的组合,其中1 <= m <= n;
设总组合数为Comb(n , m) = Comb(n , 1) + Comb(n , 2) + Comb(n , 3) + ......+ Comb(n , n);
递归求解:
从首字符开始扫描,若被选中,则递归求解:Comb(n - 1 , m - 1);
若未被选中,则递归求解:Comb(n - 1 , m);
递归终止条件: n = 0 或者 m = 0;
代码实现:
例如:字符串:abc 全排列:(abc , acb) , (bac , bca) , (cba , cab);
解题思路:
递归实现:从字符串中“依次”选择一个字符作为“首字符”,并在该“首字符”前提下,对剩余字符进行递归全排列处理;
“依次”:即始终在“初始字符串”的前提下,后面的字符分别于第一个字符交换;
字符串abc:
(abc)首字符a-->求剩余bc全排列:abc , acb;-->(a,b)交换-->bac;
(bac)首字符b-->求剩余ac全排列:bac , bca;-->(a,b)交换-->abc(以便在此基础上得到cba)-->(a,c)交换-->cba;
(cba)首字符c-->求剩余ba全排列:cba,cab;
算法递归实现:
#include<iostream> using namespace std; //------------------------------------------------------------------------------------------------------------------ void Permutation(char* pStr , char* pBegin); void Swap(char *ch1 , char *ch2); //------------------------------------------------------------------------------------------------------------------- void Swap(char *ch1 , char *ch2) { char temp = *ch1; *ch1 = *ch2; *ch2 = temp; } //不能保证出现重复排列。 void Permutation(char* pStr , char* pBegin) { if(*pBegin == '\0') { printf("%s\n" , pStr); } else for(char* pch = pBegin; *pch != '\0'; ++pch) { Swap(pch , pBegin); Permutation(pStr , pBegin + 1); Swap(pch , pBegin); } } void Permutation(char* pStr) { if(pStr == NULL) return ; Permutation(pStr , pStr); }
但是若字符串中出现重复的字符,两者交换。全排列中会出现重复的结果。这样不仅加大工作量,而且还是没有意义的,故应该去掉重复的全排列结果。
怎么去除呢?
规则:从首字符起,每个字符依次与后面不重复的字符交换。
例子:字符串abb;
(abb)首字符a-->求剩余全排列:abb-->(b,b)相等不交换;-->(a,b)交换bab;
(bab)首字符b-->求剩余全排列:bab , bba;-->(b,a)交换abb-->由于二三字符b ,b 相同,故a不再与第三个字符交换,结束;
代码实现:
#include<iostream> using namespace std; //------------------------------------------------------------------------------------------------------------------------ bool IsSwap(char* pBegin , char* pEnd); //判断是否有字符相等 void Permutation(char* pStr , char *pBegin); //------------------------------------------------------------------------------------------------------------------------ void Permutation(char* pStr) { if(!pStr) return; Permutation(pStr , pStr); } //在[nBegin,nEnd)区间中是否有字符与下标为pEnd的字符相等 bool IsSwaped(char* pBegin , char* pEnd) { char *S; for(S = pBegin ; S < pEnd ; S++) { if(*S == *pEnd) return false; } return true; } void Permutation(char* pStr , char *pBegin) { if(*pBegin == '\0') { printf("%s\n",pStr); } else { //依次与首字符交换,固定。剩余递归进行全排列 for(char *pCh = pBegin; *pCh != '\0'; pCh++) { if(IsSwaped(pBegin , pCh)) { swap(*pBegin , *pCh); Permutation(pStr , pBegin + 1); swap(*pBegin , *pCh); } } } }
字符串的组合问题:
问题描述:给定一个字符串,求该字符串中所有字符的组合;例如abc,所求组合为:a , b , c , ab , ac , bc , abc;
长度为n的字符串,选取m个字符的组合,其中1 <= m <= n;
设总组合数为Comb(n , m) = Comb(n , 1) + Comb(n , 2) + Comb(n , 3) + ......+ Comb(n , n);
递归求解:
从首字符开始扫描,若被选中,则递归求解:Comb(n - 1 , m - 1);
若未被选中,则递归求解:Comb(n - 1 , m);
递归终止条件: n = 0 或者 m = 0;
代码实现:
#include<iostream> #include<vector> #include<cstring> using namespace std; //------------------------------------------------------------------------------------------------------------------ void Combination(char* pStr , int m , vector<char>& result); //------------------------------------------------------------------------------------------------------------------- //函数功能:求一个字符串的所有组合 //参数:字符串pStr void Combination(char* pStr) { if(pStr == NULL) return; vector<char> result; int length = strlen(pStr); for(int i = 1; i <= length; i++) Combination(pStr , i , result); } //函数功能:从一个字符串中选取m个字符 //参数:字符串pStr ,选取元素个数m , 存放结果result void Combination(char* pStr , int m , vector<char>& result) { if(pStr == NULL || (*pStr == '\0' && m != 0)) return; //递归终止条件 if(m == 0) { vector<char>::iterator iter = result.begin(); for( ; iter != result.end(); iter++) cout<<*iter<<' '; cout<<endl; return; //注意 } //选中此元素 result.push_back(*pStr); Combination(pStr + 1 , m - 1 , result); result.pop_back(); //未选中此元素 Combination(pStr + 1 , m , result); } //---------------------------------------------------------------------------------------------------------------- int main() { char string1 [] = " "; Combination(string1); char string2[] = "accd"; Combination(string2); return 0 ; }
相关文章推荐
- unity3d LitJson 各种嵌套
- 第一次来,mark一下
- 神奇的勺子
- 将Vim改造为强大的IDE—Vim集成Ctags/Taglist/Cscope/Winmanager/NERDTree/OmniCppComplete(有图有真相)
- HDU4474_Yet Another Multiple Problem
- vs 窗体继承
- android Message类源代码解析
- Deque
- 搞定面试官
- 一个2013届毕业生(踏上IT行业)的迷茫(5)
- Visual c++ 项目开发案例 全程实录 源代码
- 查询长事务SQL
- 用OpenGL实现DDA画线算法
- 一个2013届毕业生(踏上IT行业)的迷茫(5)
- zoj 3658(坑坑坑!)
- 3D模型动画技术 - 皮肤变形计算(skinned meshes)
- cocos2dx一个场景添加多个层
- 一个2013届毕业生(踏上IT行业)的迷茫(4)
- VC 2008 Express下安装OpenCV2.3.1
- 一个2013届毕业生(踏上IT行业)的迷茫(4)