排列组合过滤求和(原创)

    题如下:自然数1,2,3...19这19个数字,使用其中任意组合,使之组合之和为20,
这些数字不能重复使用,不区分先后顺序,求这些组合的个数为多少,请列举出来。
eg:1+19=20,2+18=20,3+7+10=20,1+3+4+5+7=20......

 

 

 

/**
*created by zxb 
*Email:zxbxiaobo@sina.com
*date  2010-6-17 - 下午02:34:49 
*zxb 开源测试项目 test
*to do TODO
*java version "1.5.0_06"
**/

package com.java.algorism.mycombine;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * 题如下:自然数1,2,3...19这19个数字,使用其中任意组合,使之组合之和为20,
 * 这些数字不能重复使用,不区分先后顺序,求这些组合的个数为多少,请列举出来。
 * eg:1+19=20,2+18=20,3+7+10=20,1+3+4+5+7=20......;
 * 分析:估算这些组合的可能性情况只有在2,3,4,5个数之间数字符号的组合才能完成和为20的数字组合
 * 所以把这些排列组合的一一单独列举出来,判断满足组合为20的组合。
 * 63
 *@author zxb
 */
public class CombineSum extends CombineSelf{

	public static void main(String[] args) {
		long l1=System.currentTimeMillis();
		List<String> list=new ArrayList<String>();
		for (int i = 1; i < 20; i++) {
			list.add(i+"");
		}
		for (int i = 2; i < 6; i++) {
			NUM=i;
			generate(list,new ArrayList<String>());
			FILTER=20;
		}
		filterByValue();
		System.out.println("---------最终确定的值--------");
		showValue(CombineSelf.set1);
		//System.out.println("最终确定的个数--------"+CombineSelf.set.size());//16644
		System.out.println("最终确定的个数--------"+set1.size());//63
		long l2=System.currentTimeMillis();
		System.out.println("最终耗时:"+(l2-l1)+" 毫秒。");
	}	
}

class CombineSelf {
	// 将NUM设置为待排列数组的长度即实现全排列
	protected static int NUM = 3;
	//排列个数
	protected static int COUNT = 0;
	//过滤条件值
	protected static int FILTER = 20;
	//排列组合总个数
	protected static Set<String> set=new HashSet<String>();
	//排列组合满足条件个数
	protected static Set<String> set1=new HashSet<String>();
	
	/**
	 * 递归算法:将数据分为两部分,递归将数据从左侧移右侧实现全排列
	 * 
	 * @param source
	 * @param target
	 */
	protected static void generate(List<String> source, List<String> target) {
		Collections.sort(target);
		StringBuilder sb=new StringBuilder();
		if (target.size() == NUM) {
			for (String str : target){
				sb.append(str).append(",");
			}
			sb.setLength(sb.length()-1);
			set.add(sb.toString());
			return;
		}
		for (int i = 0, len = source.size(); i < len; i++) {
			List<String> newSource = new ArrayList<String>(source);
			List<String> newTarget = new ArrayList<String>(target);
			newTarget.add(newSource.get(i));
			newSource.remove(i);
			generate(newSource, newTarget);
		}
	}
	
	/**
	 * 展示其值
	 * @param set
	 */
	protected static void showValue(Set<String> set){
		Iterator<String> it=set.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
	
	/**
	 * 根据条件过滤其值
	 * @param set
	 */
	protected static void filterByValue(){
		Iterator<String> it=set.iterator();
		String[] strArr=new String[NUM];
		String temp="";
		int sum=0,i=0;
		while(it.hasNext()){
			temp=it.next();
			strArr=temp.split(",");
			sum=0;
			for ( i= 0, len = strArr.length; i < len; i++) {
				sum+=Integer.parseInt(strArr[i]);
			}
			if(sum==FILTER){
				set1.add(temp);
			}
		}
	}
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值