求字符串中字符全排列 和 组合
2015-09-25 15:01
232 查看
<span style="font-size:18px;">(1)若不考虑字符串中有重复字符(即假设字符串中无重复字符) (2)若考虑字符串中有重复字符(即假设字符串中有重复字符) <br style="" /></span>(2)若考虑字符串中有重复字符(即假设字符串中有重复字符)
上述思路非常好,但是若存在重复字符,则就不正确了,比如对于上述程序,输入“aabc”,则输出:
就会出现重复的结果。我本来思考着如果在与*pBegin交换时加一个条件语句判断是否相等,若与*pBegin相等就不交换,若不相等才交换,用“aabc”测试时结果确实正确了。但是实际上是错误的,比如用“abbc”测试时就不正确了。 我也是看到了一个网友的方法才发现我上述考虑的方法是错误的,他的方法是判断当前*pCh的字符(即准备与*pBegin交换的字符)在前面的子字符串中是否出现过了,若出现了,就不交换,若没出现就交换。代码如下:
<span style="font-size:18px;"><pre name="code" class="cpp">void Permutation(char* pSrc, char* pBegin) { if (!pSrc || !pBegin) { return; } if (*pBegin == '\0') { printf("%s\n", pSrc); } else { for (char* pCh=pBegin; *pCh!='\0'; ++pCh) { if(strchr(pBegin, *pCh) == pCh) { char temp = *pBegin; *pBegin = *pCh; *pCh = temp; Permutation(pSrc, pBegin+1); temp = *pBegin; *pBegin = *pCh; *pCh = temp; } } } } int main() { char pSrc[] = "abbc"; Permutation(pSrc, pSrc); return 0; }</span>
运行结果是:
二、字符串的组合
(1)若不考虑字符串中有重复字符(即假设字符串中无重复字符)
输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入"abc",它的组合有a、b、c、ab、ac、bc、abc。
本题也可以用递归的思路来求字符串的组合。
假设我们想在长度为n的字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符;而是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。这两种选择都很容易用递归实现。下面是这种思路的参考代码:
<span style="font-size:18px;">void Combination(char* str, int number, vector<char>& result) { if (str==NULL) { return; } if (number==0) { for (vector<char>::iterator ite = result.begin(); ite!=result.end(); ++ite) { cout<<*ite; } cout<<endl; return; } if (*str == '\0') { return; } else { Combination(str+1, number, result); result.push_back(*str); Combination(str+1, number-1, result); result.pop_back(); } } int main() { char pSrc[] = "abc"; vector<char> result; for (int i=1; i<=strlen(pSrc); ++i) { Combination(pSrc, i, result); } return 0; }</span>
运行结果是:
也可以去掉上述中的循环:
<span style="font-size:18px;"><pre name="code" class="cpp">void Combination(char* str, int number, vector<char>& result) { if(*str == 4000 '\0') { for(vector<char>::iterator ite = result.begin(); ite != result.end(); ++ite) { cout<<*ite; } cout<<endl; return; } result.push_back(*str); Combination(str + 1, number - 1, result); result.pop_back(); Combination(str + 1, number-1, result); } int main() { char pSrc[] = "abc"; vector<char> result; Combination(pSrc, strlen(pSrc), result); return 0; }</span>
另外,看到一个网友的思路:用一个数组,模拟2进制加法器,某一个为1,则取对应的字符,若为0则不取,就能够实现字符组合。这个思路也非常好~ 不过是在字符长度不超过32的情况下。
(2)若考虑字符串中有重复字符(即假设字符串中有重复字符) 但是上述代码在字符串中有重复字符时就出问题了,如输入”abbc“,则输出为:
<span style="font-size:18px;">void Combination(char* str, int number, vector<char>& result) { if (str==NULL) { return; } if (number==0) { for (vector<char>::iterator ite = result.begin(); ite!=result.end(); ++ite) { cout<<*ite; } cout<<endl; return; } if (*str == '\0') { return; } else { Combination(str+1, number, result); result.push_back(*str); Combination(str+1, number-1, result); result.pop_back(); } } int main() { char pSrc[] = "abc"; vector<char> result; for (int i=1; i<=strlen(pSrc); ++i) { Combination(pSrc, i, result); } return 0; }</span>
相关文章推荐
- Redis Cluster架构优化
- Android setArguments()和 Intent.putExtra()的用法之却别
- 机房收费系统测试分析报告
- IOS 清除UIWebview的缓存以及cookie
- Redis Cluster架构优化
- JavaScript中常用函数(入门级)(持续更新)
- NSURLSession学习笔记(二)Session Task
- Activity
- Spring in Action 第一部分学习笔记
- Android如何监听蓝牙耳机的按键事件
- 由于域名解析引起的dataguard传输日志故障
- onInterceptTouchEvent() 和 onTouchEvent()
- 校园宿舍网的搭建及简单原理分析
- SpringMvc一个简单的框架入门程序
- MyEclipse 2015 Stable 2.0破解方法
- 网站技术笔记-演化
- hust1384---The value of F[n]
- IPv6 tutorial – Part 5: Address types and global unicast addresses
- maven的配置和eclipse maven插件安装
- Threatening letter in Naver Line App