牛客网剑指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()之间的东西。请记住这个用法!

 

posted @ 2020-03-01 22:35  少年π  阅读(347)  评论(0编辑  收藏  举报