列出所有组合
combinations([1,2,3,4],2);
可以从两个角度思考
第一个角度:从中取出一个,然后再取出一个,这样频发的从数组中取走元素,效率不高
第二个角度:先考虑第一个元素,选择取或者不取,取的话再在剩下的数组以此方法再取走一个(问题规模缩小),不取的话,除去第一个元素外,剩下的数组以此方法取走2个(问题规模缩小),如下所示:
选1——combination([2,3,4],1)
不选1——combination([2,3,4],2)
代码如下:
package com.sise.recursion;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Combination {
/*
* 输出所有元素组合,从data中选取n个元素
* data 传入的元素集合
* n 要选取的元素个数
*/
public static void combinations(List<Integer> selected,List<Integer> data,int n){
// //-----特殊处理,如果是空集------,
// if(data.isEmpty()){
// if(n==0){
// //从0个元素中选取0个是可以的,选出空集
// //输出组合
// }
// return;
// }
//
if(n<0){
//处理n<0的特殊情况
return;
}
//
// if(n==0){
// //此时n==0已经return,因此n不会小于0
// //输出组合
// return;
// }
//合并上面的代码
if(n==0){
//n为0,说明前面已经选够了元素了
//输出组合
for (Integer i : selected) {
System.out.print(i);
System.out.print(" ");
}
System.out.println();
return;
}
if(data.isEmpty()){
return;
}
//选择第0号元素
//---如果集合为空,取不到第0号元素----
//---如果n为0传进来,此处会返回一个n<0---
//加入第0个元素到组合中
selected.add(data.get(0));
combinations(selected,data.subList(1, data.size()), n-1);
//不选择第0号元素
//remove掉selected最后加上的元素
selected.remove(selected.size()-1);
combinations(selected,data.subList(1, data.size()), n);
}
public static void main(String[] args) {
Combination comb=new Combination();
List<Integer> selected=new ArrayList<>();
List<Integer> data=new ArrayList<>();
comb.combinations(selected,Arrays.asList(1,2,3,4), 2);
System.out.println("==============");
comb.combinations(selected,data, 2);
System.out.println("==============");
comb.combinations(selected,data, 0);
System.out.println("==============");
comb.combinations(selected,Arrays.asList(1,2,3,4), 1);
System.out.println("==============");
comb.combinations(selected,Arrays.asList(1,2,3,4), 0);
System.out.println("==============");
comb.combinations(selected,Arrays.asList(1,2,3,4,5,6,7,8,9,10), 4);
}
}
运行结果: