笔试面试题(9)----字符串全排列
2014-03-20 16:42
148 查看
不同字符的全排列.
用C++写一个函数, 如 Foo(const char *str), 打印出 str 的全排列,
如 abc 的全排列: abc, acb, bca, dac, cab, cba
一、全排列的递归实现
123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。找到这个规律后,递归的代码就很容易写出来了.
二、去掉重复的全排列的递归实现
由于全排列就是从第一个数字起每个数分别与它后面的数字交换。我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这二个数就不交换了。如122,第一个数与后面交换得212、221。然后122中第二数就不用与第三个数交换了,但对212,它第二个数与第三个数是不相同的,交换之后得到221。与由122中第一个数与第三个数交换所得的221重复了。所以这个方法不行。
换种思维,对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。
这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。
用C++写一个函数, 如 Foo(const char *str), 打印出 str 的全排列,
如 abc 的全排列: abc, acb, bca, dac, cab, cba
一、全排列的递归实现
123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。找到这个规律后,递归的代码就很容易写出来了.
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int sum=0; int n; void nextper(char *str,int k,int n) { if(k==n) { cout<<sum++<<" : "<<str<<endl; return ; } else { for(int i=k;i<n;i++) { swap(str[k],str[i]); nextper(str,k+1,n); swap(str[k],str[i]); } } } int main() { char str[1000]; scanf("%s",str); n=strlen(str); nextper(str,0,n); return 0; }
二、去掉重复的全排列的递归实现
由于全排列就是从第一个数字起每个数分别与它后面的数字交换。我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这二个数就不交换了。如122,第一个数与后面交换得212、221。然后122中第二数就不用与第三个数交换了,但对212,它第二个数与第三个数是不相同的,交换之后得到221。与由122中第一个数与第三个数交换所得的221重复了。所以这个方法不行。
换种思维,对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。
这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int sum=0; int n; bool is_swap(char *str,int s,int e ) { for(int i=s;i<e;i++) { if(str[i]==str[e]) return 0; } return 1; } void nextper(char *str,int k,int n) { if(k==n) { cout<<sum++<<" : "<<str<<endl; return ; } else { for(int i=k;i<n;i++) { if(is_swap(str,k,i)) { swap(str[k],str[i]); nextper(str,k+1,n); swap(str[k],str[i]); } } } } int main() { char str[1000]; scanf("%s",str); n=strlen(str); nextper(str,0,n); return 0; }
相关文章推荐
- 剑指offer之面试题28:字符串的排列
- 剑指offer--面试题28:字符串的排列--Java实现
- 关于"字符串"的笔试,面试题
- 【剑指offer】面试题28:字符串的排列
- 笔试面试题12--字符串拷贝、链接、比较无库函数实现
- 剑指offer-面试题28 字符串的排列
- 面试题28:字符串全排列
- 常见算法笔试题的研究3(字符串的排列种数)
- 剑指offer面试题28:字符串的排列
- 剑指Offer----面试题28:字符串的排列 & 去重
- 剑指offer--面试题28:字符串的排列--Java实现
- 面试题28:字符串的排列
- 面试题32:字符串的排列
- 【C语言】【笔试题】【面试题】判断一个字符串是否为另外一个字符串旋转之后的字符串
- 剑指offer 面试题28 字符串的排列与集合的所有子集
- 【剑指Offer学习】【面试题28 :字符串的排列】
- 剑指offer面试题之字符串的排列
- 程序员面试题精选100题(28)-字符串的排列[算法]
- 笔试面试题解备忘1:字符串转换成整数
- 海涛老师的面试题-作业28-字符串的排列组合问题。