今天,遇到一个同事的问题,要求给定从给定的5个不重复的数字中,取出3个数字,输出所有的组合情况。其实就是数学中的组合问题。以前仅仅做的是关于求出组合的情况数,这个很简单,用递归就可以求解。这题要求列举出所有情况。在网上进行一阵狂搜,最后找到了一个比较好理解的算法,叫“二进制置换算法”,先姑且这样叫吧。算法思想如下:
1、先定义一个数组,用1和0进行组合。其中1和0的总数为5个(即M),1表示命中(或被选中),所以1的总数为3(N)个。
2、那么初始状态可以设置为11100,称为一个状态码。
3、对初始状态是5选3的一种状态,再对这种状态进行后续分析。
4、分析如下:
a.从左到右,遇到第一次出现的10组合时,将其置为01。
b.判断最左边的第1位,如果为1,继续重复a步骤。如果为0,则将置换点之前的1移动到最左边。然后,再重复a步骤。
c.所有情况置换结束的条件是不再出现10组合,即表示已经得到了所有的情况。
5、根据第4步得到的所有状态码进行分析,将所有为1的位置,输出数组中对应的信息,即可得到一个数组的所有情况。
例如:
1 1 1 0 0
1 1 0 1 0
1 0 1 1 0
0 1 1 1 0
1 1 0 0 1
1 0 1 0 1
0 1 1 0 1
1 0 0 1 1
0 1 0 1 1
0 0 1 1 1//该状态码中不再出现10信息,即置换结束
代码如下:
public class Util {
//构造2进制字符串
public static String stringConstruction(int m,int n){
String testsString="";
for(int i=1;in)
testsString=testsString+"0";
else
testsString=testsString+"1";
}
return testsString;
}
//二进制置换算法
public static List allConditons(String s){
List list = new ArrayList();
list.add(s);
//;
while(true){
int length = list.size()-1;
//标志位
int flag = list.get(length).indexOf("10");
if(flag0){
list.add(last.replaceFirst("10", "01"));
}
else {
//先将10变成01
String ss = last.replaceFirst("10", "01");
//将10前面的内容反置
String before = last.substring(0,last.indexOf("10"));
StringBuffer sb = new StringBuffer(before);
String after=sb.reverse().toString();
list.add(ss.replaceFirst(before, after));
}
}
return list;
}
//通过置换算法获取自由组合
public static List result(String[] r,List list){
List ttList =new ArrayList();
for(int i=0;i hs = new HashSet(ttList);
ttList.clear();
ttList.addAll(hs);
return ttList;
}
} 来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2143/viewspace-2799065/ ,如需转载,请注明出处,否则将追究法律责任。