含有重复字符的全排列问题以及按字典序打印
2017-09-24 17:55
204 查看
关于字符的全排列问题也是有很多算法的,今天我就来介绍递归的Perm算法。直接看题吧。。。
给定一字符串,可能含有相同元素。请借助递归设计算法求出该字符串的所有不同的排序。
输入格式:
给定一串字符串(长度小于等于9,且至少有3个字符相同)。
输出格式:
每行输出一个字符串。按照字典序递增的顺序输出,每个排列占一行。
最后一行输出不同排列的个数。
题目大体意思就是要我们求一个字符串的全排列,说到递归,那么Perm算法出来了,Perm算法核心思想是把m个待排元素每一个依次拿到首位,剩下的m-1个组成新的待排元素传入Perm进行相同的操作……….以此类推,直到元素递归到只有一个了,就依次打印出来 形成一个排列
先上算法的核心部分:
这只是Perm最原始思想的体现,目前还不具备处理重复元素的能力,比如aabc,把第一个a拿到首位和把第二个a拿到首位,再让其与字符进行全排列后的效果是一样的,因此,我们在交换前应该加一个判断,如果在该字符位置之前存在相同的字符,该字符就不进行多余的交换了,跳往下一个字符的判断,修改代码如下:
当然了,到目前位置还存在的一个问题就是没有满足字典序打印的问题,由于该算法是一个元素一个元素输出的,所以没有办法在得到结果之后在进行排序,只得对算法本身加以调整,如下:
这样工作就都做完啦。。
这一题完整代码如下:
给定一字符串,可能含有相同元素。请借助递归设计算法求出该字符串的所有不同的排序。
输入格式:
给定一串字符串(长度小于等于9,且至少有3个字符相同)。
输出格式:
每行输出一个字符串。按照字典序递增的顺序输出,每个排列占一行。
最后一行输出不同排列的个数。
题目大体意思就是要我们求一个字符串的全排列,说到递归,那么Perm算法出来了,Perm算法核心思想是把m个待排元素每一个依次拿到首位,剩下的m-1个组成新的待排元素传入Perm进行相同的操作……….以此类推,直到元素递归到只有一个了,就依次打印出来 形成一个排列
先上算法的核心部分:
void Perm(char b[],int low,int high,int& n)//这里把待排序元素放入char型数组b中,待排元素起始下 //标为low,末尾下标为high,n用来计有多少种不同的排列组合 { if(low == high) //如果递归排到只有最后一个元素,就按序打印出来 { for(int i = 0;i < low;i++) { printf("%c",b[i]); } n++; //打印一次计数值加1 printf("\n"); //每打印一次排列就换一次行 } else //如果传进来的待排字符不止一个字符 { for(int i = low;i < high;i++) { swap(b[low],b[i]); //把每个元素挨个拿到首部low的位置 Perm(b,low+1,high,n); //除拿到首部之外剩下的再进入Perm递归 swap(b[low],b[i]); //还原字符串为交换前的样子,以进行下个字符的交换 } } }
这只是Perm最原始思想的体现,目前还不具备处理重复元素的能力,比如aabc,把第一个a拿到首位和把第二个a拿到首位,再让其与字符进行全排列后的效果是一样的,因此,我们在交换前应该加一个判断,如果在该字符位置之前存在相同的字符,该字符就不进行多余的交换了,跳往下一个字符的判断,修改代码如下:
for(int i = low;i < high;i++) { if(isSwap(b,low,i)) //交换前判断之前是否有相同的元素被拿到首位过 { swap(b[low],b[i]); Perm(b,low+1,high,n); swap(b[low],b[i]); } }
当然了,到目前位置还存在的一个问题就是没有满足字典序打印的问题,由于该算法是一个元素一个元素输出的,所以没有办法在得到结果之后在进行排序,只得对算法本身加以调整,如下:
for(int i = low;i < high;i++) { sort(b+low,b+high);//把每次递归传进来的元素先排个序,用了sort库函数,它包含在在头文件<algorithm>中 if(isSwap(b,low,i)) { swap(b[low],b[i]); Perm(b,low+1,high,n); swap(b[low],b[i]); } }
这样工作就都做完啦。。
这一题完整代码如下:
#include<iostream> #include<algorithm> using namespace std; void swap(char& a,char& b) //两个元素进行交换 { char c = a; a = b; b = c; } bool isSwap(char b[], int start, int i) //i为该元素下标 { for(int k = start; k<i;k++) //判断在该元素之前有没有相同元素 if(b[k] == b[i]) return false; //如果有,则返回false return true; } void Perm(char b[],int low,int high,int& n) //核心的算法啦 { if(low == high) { for(int i = 0;i < low;i++) { printf("%c",b[i]); } n++; printf("\n"); } else { for(int i = low;i < high;i++) { sort(b+low,b+high); if(isSwap(b,low,i)) { swap(b[low],b[i]); Perm(b,low+1,high,n); swap(b[low],b[i]); } } } } int main() { int n = 0; //计数用的 string str; cin>>str; //用字符串接收待排元素 char b[9] ; int i = 0; while(str[i]!='\0') { b[i] = str[i]; //把待排元素装进字符数组中 i++; } Perm(b,0,str.length(),n); //调用Perm进行排序 cout<<n<<endl; //输出总排列个数 }
相关文章推荐
- 每天一道算法题(39)——含有重复字符的全排列
- 每天一道算法题(39)——含有重复字符的全排列
- 递归解决输出一个字符串的全排列问题(缺陷:没有考虑字符串中字符重复的问题)
- 字符串全排列问题(递归解决有重复字符问题)
- 字符全排列、全组合以及相关问题
- 字符串的全排列问题(一)——无重复出现字符的排列
- n个不重复的字符全排列问题 康托展开小结
- 含重复字符的字符串的全排列问题(Java)
- Android studio关于含有转义字符的字符串无法Log,以及如何去掉转义字符问题
- 2.写出一个程序,接受一个有字母和数字以及空格组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数。不区分大小写。
- All About JAVA 关于英文服务器下输出含有中文字符文件乱码的问题
- 学习struts2建bbs总结五:使用jquery+ajax验证用户名是否存在以及struts效验信息不断重复的问题
- 找到100亿个url中重复的url以及搜索词汇的topk问题
- 动态使用webservice,以及含有ref类型的参数的问题
- 重复提交、重复刷新、防止后退的问题以及处理方法
- 字符串匹配问题——求给定字符串的next数组以及KMP算法实现
- 关于oracle重复数据合并以及.前面加0问题的解决
- 关于delphi中url文件下载编码问题(处理里面含有空格,汉字,字符)
- 【LeetCode31-40】全排列,栈的用法,find用法,数独规则及解法,数列,类似找钱问题找出所有可能,不允许重复的找钱问题
- 获取中文字符长度遇到的问题,以及解决方法