获取组合数

参考这篇博客的方法http://blog.youkuaiyun.com/randyjiawenjie/article/details/6784355

方法思路:用一个位数组来表示组合数的一种组合情况。比如C(n,m),m个数里面,n个数的不同组合情况。可以表示成11..100...0其中1的个数代表这个数字出现在组合中,0所在的位数代表这个数字没有出现在组合中。比如,C(3,5),对于数字1到5来说,其中一种组合情况就是123,表示成位数组就是11100;另一种组合情况,比如134,表示成10110。现在通过有规律的移动每一位上的1,来找出所有的排列数,比如C(3,5)


那篇博客里给出的描述不是很清晰,我再用自己的语言描述一下,加深记忆。首先从11100开始,从左到右寻找10组合,如果找到一个10组合,就将两个位置上的1和0调换位置。并且,对于新调换位置后的那个1,对他前面的子数组里的各位元素,重复从左到右寻找10组合的过程,并调换。重复这个过程,直到子数组里不再有10组合,则向上返回,继续探测父数组的10组合,发现后,再对新交换的1前面的子数组进行探测,知道找到所有情况。


乍一看这个方法,就是一个寻找10组合并置换的方法,但他有个恼人的地方,就是原数组置换之后,只能对置换的那个1前面的子数组置换。一开始没有看清这个子数组的关系,输出的结果有很多重复项,后来增加了一个位置标记,用来告诉下一次调用,循环探测到哪个位置停止,结果就正常了。


下面是用迭代的方法的实现


import java.util.ArrayList;

public class TEST{	
	public static ArrayList<ArrayList<Integer>> alllist = new ArrayList<ArrayList<Integer>>();
	public static void main(String[] args){
		System.out.println("test:");
		int m = 6;
		int n = 3;
		ArrayList<Integer> arr = new ArrayList<Integer>();
		for(int i = 0; i< m; i++){
			arr.add(0);
		}
		for(int i = 0; i< n; i++){
			arr.set(i, 1);
		}
		rearrange(arr, m);
		
		for(int i = 0; i< alllist.size(); i++){
			for(int j= 0; j< alllist.get(i).size(); j++){
				System.out.print(alllist.get(i).get(j));
				System.out.print(",");
			}
			System.out.println();
		}
	}
	
	public static void rearrange(ArrayList<Integer> arr, int m){
		ArrayList<Integer> ins;
		ins = new ArrayList<Integer>();
		ins.addAll(arr);
		alllist.add(ins);
		
		for(int i = 1; i< m; i++){
			if(arr.get(i-1)== 1 && arr.get(i)== 0){
				ins = new ArrayList<Integer>();
				arr.set(i-1, 0);
				arr.set(i, 1);
				ins.addAll(arr);
				rearrange(ins, i);
			}
		}
		return;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值