作者:changmao三顾茅庐 | 来源:互联网 | 2023-10-10 15:46
之前做过很多类似的题目,比如说给你一个字符串ABC,然后请给出他的子集(A,B,C,AB,AC,BC,ABC),差不多都是这样的,当然也有给你ABC,请给出跟其长度一样的组合(ABC,ACB,BAC,BCA,CAB,CBA)等等。由于这种题目都是涉及到排列组合数学,因此这里来总结一下。
1.首先我们来讨论第一种情况,即给出一个集合,求出其子集。
从数学角度,我们可以知道,拥有n个元素的集合,它拥有2 n 个子集(包含空集的情况),因此我们的复杂度不可能会低于2 n 。
下面我们使用递归的方法来求。
终止条件:n = 0; 空集合只有一个子集{ }。
集合{a 1 }有2个子集:{ }和{a 1 }.
集合{a 1 ,a 2 }有四个子集:{ },{a 1 },{a 2 },{a 1 ,a 2 }。
从上面我们继续往下推断,我们应该如何使用p(2)来构造p(3)?
答案是复制p(2),并在这些子集中添加a 3 ,然后再将p(2)与其合并,即可产生p(3);
下面是实现上述思路的代码:
public ArrayList< ArrayList< Integer >> getR(ArrayList< Integer > set , int index){ArrayList< ArrayList< Integer >> allsubsets;if (set . size() &#61;&#61; index){allsubsets &#61; new ArrayList< ArrayList< Integer >> ();allsubsets. add(new ArrayList< Integer > ());} else {allsubsets &#61; getR(set , index &#43; 1 );int item &#61; set . get(index);ArrayList< ArrayList< Integer >> biggersubsets &#61; new ArrayList< ArrayList< Integer >> ();for (ArrayList< Integer > subset : allsubsets){ArrayList< Integer > newlist &#61; new ArrayList<> ();newlist. addAll(subset);newlist. add(item);biggersubsets. add(newlist);}allsubsets. addAll(biggersubsets);}return allsubsets;}
另外一种思路是&#xff0c;每个元素在子集中的出现都是2种情况&#xff0c;有或者没有这种元素&#xff0c;因此我们构造0-2 n − 1 个连续的二进制数&#xff0c;用他们每一位的表示来标识元素出现的情况。
下面是代码&#xff1a;
public ArrayList> getSub (ArrayList set ){ArrayList> allsubsets &#61; new ArrayList>();int max &#61; 1 <<set .size();for (int k &#61; 0 ; k subset &#61; convertIntToset(k, set );allsubsets.add(subset);}return allsubsets;}public ArrayList convertIntToset (int x, ArrayList set ){ArrayList subset &#61; new ArrayList<>();int index &#61; 0 ;for (int k &#61; x; k > 0 ; k >>&#61; 1 ){if ((k & 1 ) &#61;&#61; 1 ){subset.add(set .get (index));}index&#43;&#43;;}return subset;}
第二种情况是不求子集&#xff0c;而是求组合的情况。
详细见我的这篇博客