本算法的目的: 给定一组数字,求这些数字的所有可能的排序组合。
算法内部逻辑:模拟人进行排列组合的过程。
1. 假设仅有2个数字, 则交换其位置,可以得到所有可能的组合,也即2组。
2. 假设有3个数字。则取出第1个数字,将第2和第3个数字交换位置后得到2种组合,然后在每种组合的开头插入第1个数字。得到了3个数字排列组合的其中两种;
然后取出第2个数字,将第1和第3个数字交换位置后得到2种组合,然后在每种组合的开头插入第2个数字。又得到了3个数字排列组合的其中两种
接着取出第3个数字,将第1和第2个数字交换位置后得到2种组合,然后在每种组合的开头插入第3个数字。又得到了3个数字排列组合的其中两种。至此,我们得到了3个数字的所有排列组合(6种)
3. 假设有4个数字。与3个数字一样,依次取出其中的某一个,将剩余的3个进行排列得到6种组合,然后在这6种组合的开头插入一开始取出的那个元素。这样,遍历这4个数字一遍之后,可以得到一共4*6=24种组合。
4. 假设有5个数字,同理:依据步骤2或3或4的逻辑,把大的数组化小,得到较小的数组返回的可能的排列组合后,再拼接成较大的数组的排列组合。
上述的分析过程表明可以使用递归的方法进行实现。具体实现代码如下:
public class Combine {
public static void main(String[] args) {
List<Integer> a = new ArrayList<Integer>(4);
a.add(1);
a.add(2);
a.add(3);
a.add(4);
a.add(5);
int count = 0;
List<List<Integer>> resList = combination(a);
for (List<Integer> intList : resList) {
count++;
for (Integer i : intList) {
System.out.print(i + ", ");
}
System.out.println();
}
System.out.println("一共有 " + count + " 种组合");
}
public static List<List<Integer>> combination(List<Integer> list) {
if (list.size() == 1) {
throw new IllegalArgumentException("the size of list must be lager than one");
}
List<List<Integer>> result = new ArrayList<List<Integer>>();
int size = list.size();
if (size == 2) {
List<Integer> list1 = new ArrayList<>();
list1.add(list.get(0));
list1.add(list.get(1));
List<Integer> list2 = new ArrayList<>();
list2.add(list.get(1));
list2.add(list.get(0));
result.add(list1);
result.add(list2);
} else if (size > 2) {
for (int i = 0; i < list.size(); i++) {
List<Integer> copied = new ArrayList<Integer>(list);
copied.remove(i);
List<List<Integer>> subList = combination(copied);
for (List<Integer> li : subList) {
li.add(0, list.get(i));
result.add(list);
}
}
}
return result;
}
}