在算法设计与分析里,组合排列(或者表面像排列组合)的问题很好的解决方法主要是回溯法,广度优先遍历法。
这里提供关于组合问题一种巧妙的解决办法。比如我们要从m个元素里取n个元素的所有组合。
我们用一个m位二进制数代表m个元素(一位代表一个元素)。取n个元素可以看做是这个m位二进制数中有n位的值为1.
一个m位二进制数可以代表2的m次方个值,(代表m个元素所有组合的情况)
/**
这里提供关于组合问题一种巧妙的解决办法。比如我们要从m个元素里取n个元素的所有组合。
我们用一个m位二进制数代表m个元素(一位代表一个元素)。取n个元素可以看做是这个m位二进制数中有n位的值为1.
一个m位二进制数可以代表2的m次方个值,(代表m个元素所有组合的情况)
/**
* 从m个数里取n个数的组合的个数,这里i并不是一个m位数,只是使用了i最右边的m位数
* 思路:
* @param m
* @param n
* @return
*/
public static int getCombinations(int m,int n){
int total=0;
for(long i=0l;i<Math.pow(2, m);++i){
int count=0;
//j=0表示右边第一位,j=1表示右边第二位,
for (int j = 0; j <m; j++) {
//>>>无符号右移,左边填充0,i>>>j先运算,把我们要考核的哪一位移到最右边,然后与1进行&运算,即可知道我们考核的那一位的值。
//>>>无符号右移,左边填充0,i>>>j先运算,把我们要考核的哪一位移到最右边,然后与1进行&运算,即可知道我们考核的那一位的值。
if((i>>>j&1)==1){
++count;
}
if(count>n){
break;
}
}
if(count==n){
++total;
}
}
return total;
}
/* 取组合方法
* 参数: list ---- 原始集合
* 返回: 包含所有组合的集合
*/
public static List<List<Object>> getCombinations(List<Object> list) {
List<List<Object>> result = new ArrayList<List<Object>>();
long n = (long)Math.pow(2,list.size());
List<Object> combine;
for (long l=0L; l<n; l++) {
combine = new ArrayList<Object>();
for (int i=0; i<list.size(); i++) {
if ((l>>>i&1) == 1)
combine.add(list.get(i));
}
result.add(combine);
}
return result;
}