含有重复字符的字符串排列组合

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了含有重复字符的字符串排列组合相关的知识,希望对你有一定的参考价值。

参考技术A

排列:从给定个数的元素中取出指定个数的元素进行排序
组合:从给定个数的元素中取出指定个数的元素,不考虑排序

排列包含了组合的过程,从给定个数的元素中取出指定个数元素(组合),然后再把取出的元素进行排序。

这意味着,我们利用组合得到组合数,然后利用组合数实现全排列,就得到了排列。

一般组合指的是取出1~n个元素的组合,因为全组合只有一个

输入一个长度为n的字符串,输出该字符串中字符的所有组合

如果输入"abc",它的组合有a、b、c、ab、ac、bc、abc

①假设在长度为n的字符串中求m个字符的组合
②从头扫描字符串的第一个字符,有两种选择:
(1)把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符
(2)不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符

注意:所有字符取出摆放的位置都是以原来的相对位置,不改变原来的前后顺序

基本思路 :求组合,表示可以取少于总字符个数的字符组合,因为全字符组合就一个,则假设输入字符个数为n个,则最终组合结果是(2^n - 1)个。
原因 :假设字符为a,b,c,则1表示取c元素,0表示不取c。所以001表示取c,010取b,100取a,011取bc.所以一共三位,每个位上有两个选择0,1.所以是(2^n - 1)个结果。依次表示为: 001,010,011,100,101,110,111 。对应输出组合结果为: a, b ,ab,c,ac,bc,abc .

注意:这个思路也非常好~ 但是前提是 字符长度不超过32个

利用hashSet实现查重:第一次放入到hashSet输出结果,如果遇到已经在hashSet中存在,则不输出结果

注意 :由于利用HashSet实现去重,而不是直接在算法上实现去重,增加了空间复杂度和时间复杂度,所以不是最优算法。关于算法优化,有待后面继续提高和实现!
如果网友有更好的方法,还是多多指教!

输入一个长度为n的字符串,输出该字符串中字符的全排列

如果输入“abc”,则全排列为abc、acb、bac、bca、cab和cba。

①递归实现,每递归一次取一个字符作为当前输入字符的首字符。例如,输入“abc”,则取第一个字符“a”,把字符“a”与第一个字符“a”交换,当前不用交换。剩下的字符“bc”,下次递归也是这样。如果选取的是字符“b”,则在字符数组中把字符“b”与字符“a”交换,后面选取字符就是在“ac”中选取。如果选取的是字符“c”,与字符“a”交换,下次选取就是在“ba”中选取
②每次选取后,下次递归则需要把交换的字符顺序,重新返回。

输入一个长度为n的字符串,字符中包含重复字符,输出字符的全排列

如果输入“abb”,则全排列为abb, bab, bba

参考文献
[1] 字符串的全排列和组合
[2] 字符串排列和组合的JAVA实现
[3] 字符串的全排列和组合算法
[4] 带有重复字符的字符数组的全排列
[5] java 全组合 与全排列
[6] 字符串组合——位运算
[7] java排列组合问题汇总【经典】

面试题 08.08. 有重复字符串的排列组合

题目:

技术图片

 

 

解答:

在无重复字符代码的基础上先对字符串进行排序,这样重复字符必然相邻,然后在回溯过程中加一句判断条件去除重复排列。

 1 class Solution
 2 {
 3 public:
 4     vector<string> permutation(string S)
 5     {
 6         vector<string> res;
 7         sort(S.begin(), S.end());   //先排列,使得重复字符相邻,便于后面去重
 8         backTrack(res, S, 0);
 9         return res;
10     }
11 
12     void backTrack(vector<string> &res, string S, int begin)
13     {
14         if (begin == S.size())
15         {
16             res.push_back(S);
17         }
18         for (int i = begin; i < S.size(); ++i)
19         {
20             /*因为首次交换是i == begin,S[i]与自身交换
21             因此考虑两种重复情况的去除
22             1.S[i] == S[i-1]
23             2.S[i] == S[begin]*/
24             if (i > begin && (S[i] == S[i - 1] || S[i] == S[begin]))
25             {
26                 continue;
27             }
28             else
29             {
30                 swap(S[begin], S[i]);
31                 backTrack(res, S, begin + 1);    //DFS
32                 swap(S[begin], S[i]);
33             }
34         }
35     }
36 };

 

以上是关于含有重复字符的字符串排列组合的主要内容,如果未能解决你的问题,请参考以下文章

面试题 08.08. 有重复字符串的排列组合

算法面试题 08.07. 无重复字符串的排列组合(多语言实现)

算法面试题 08.07. 无重复字符串的排列组合(多语言实现)

《程序员面试金典(第6版)》面试题 08.08. 有重复字符串的排列组合(回溯算法,全排列问题)C++

获取字符串或组合的所有可能排列,包括 Java 中的重复字符

python中的排列组合