牛客网剑指offer第27题——求字符串的全排列
题目:
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
思路:
关于这个题目的思路,我在此不进行过多的文字赘述。这个题目其实就是数学中的全排列的题目,关于全排列问题的所有相关问题,请参考下面这个网址:https://www.cnblogs.com/likaiming/p/8401086.html
当然了,我们可以采用暴力穷举法来实现,但是这样会显得繁琐,而且当存在重复元素的时候,穷举似乎稍稍有些困难了,因此这个题目给出了递归的解法:
按照习惯:先上代码:
1 class Solution { 2 private: 3 set<string>res; 4 public: 5 vector<string> Permutation(string str) { 6 vector<string> resv; 7 if(str.size() == 0 || str.size() >9) 8 return resv; 9 else 10 { 11 Permutation(str,0); 12 resv.insert(resv.end(),res.begin(),res.end()); 13 return resv; 14 } 15 } 16 void Permutation(string str, int begin) 17 { 18 if(begin == str.size()) 19 { 20 res.insert(str); 21 return; 22 } 23 for(int i = begin;str[i]!='\0';i++) 24 { 25 swap(str[begin],str[i]); 26 Permutation(str,begin+1); 27 swap(str[begin],str[i]); 28 } 29 30 } 31 };
这是一段非常朴实无华的代码,这段代码整体上就分为两步:
第一步:采用递归法求出所有可能(此时不考虑重复字符和字典排序问题)
第二步:利用set自动排序和剔除重复元素的功能完善结果。
下面来稍微总结下这个问题的思路:
我们想打印一个字符串的所有排序可能性。很显然的一个思路是:开头一个字母应当遍历完所有的字母可能性。然后求以每个字母开头的所有可能性。对于每个字母开头,其后面的字母同样构成了一个长度为n-1的字符串,对于这个字符串的考量,我们同样是上述思路:开头一个字母应当遍历完所有的可能性,然后求以每个字母开头的可能性。似乎又回到了刚才的问题,而这个就是递归。具体的思路可以参考我上面提供的那个网址。
当我们遍历完所有的可能性。要按照题目要求:考虑存在重复字母的情况,并且要按找字典顺序排列。
那么我们显然可以利用set这种数据结构实现这个功能。set中的insert会自动执行排序和过滤相同元素的功能。最后将这个set传递给vector即可。
这里,我们要提一下vector的insert,似乎我们很少使用,但是其实vector的insert很好。
代码resv.insert(resv.end(),res.begin(),res.end())表示在vector的末尾插入迭代器res.begin()和res.end()之间的东西。请记住这个用法!
stay foolish,stay hungry