• 优化后的组合算法


            项目中一个算法中涉及到了组合,大概业务是:给定一个值X,从n个数中找出能组合加起来和X相等的集合。假设用通常的组合算法。数量级是2的n的阶乘。假设记录比較多的话,有效率问题。我针对我们的业务。优化写了一个算法。

           大概逻辑:先给n个值从小到大排序形成一个队列。组合数从2開始依次递增,每次运行一个剔除操作,如果组合数递增到m。取队列中前面m-1个连续的值。并加上最大的一个值V。如果大于X,那么舍弃V。这样队列是不断缩小的。

    舍弃没用的组合。运算量也会大大降低。详细见代码:

    /**
    	 * 从list中找出金额能够凑出db的多个lend2match
    	 * list须要依据金额从小到大排序
    	 * @param listLend  list,须要凑的金额,几个出借人组合数量(第一次从2開始),開始的序号(第一次为0)
    	 * @param db
    	 */
    	
    	public static List<Lend2match> makeUp(List<Lend2match> listLend,Double db ,int num,int index) {
    		if (num>listLend.size()) {
    			//数量超出,整个list中没有合适的组合
    			return null;
    		}
    		//记录合适的makeup
    		List<Lend2match> listMakeUp=new ArrayList<Lend2match>();
    		
    		List<Lend2match> listReturn=new ArrayList<Lend2match>();
    		
    		double dbMakeUp=0;
    		//计算出最小的几个值。预留一个空缺
    		for (int i = 0; i <num-1; i++) {
    			dbMakeUp+=listLend.get(i+index).getLendAmount();
    			listMakeUp.add(listLend.get(i+index));//先存起来记录
    		}
    		Double tmp=dbMakeUp;
    		//记录要舍去的list
    		List<Lend2match> listDel=new ArrayList<Lend2match>();
    		
    		for (int i = num+index-1; i < listLend.size(); i++) {
    			dbMakeUp+=listLend.get(i).getLendAmount();
    			if (dbMakeUp==db) {//正好相等,记录并跳出
    				listMakeUp.add(listLend.get(i));
    				listReturn=listMakeUp;
    				return listReturn;   //仅仅取第一次匹配合适的记录
    			}
    			if (dbMakeUp>db) {//超出。舍去最大的那个记录
    				listDel.add(listLend.get(i));
    			}
    			dbMakeUp=tmp;//值还原
    		}
    		//删除要舍去的
    		for (Lend2match t:listDel) {
    			listLend.remove(t);
    		}
    		
    		//组合遍历
    		List<Lend2match> listRec=new ArrayList<Lend2match>();
    		listRec=traversal(listLend, listRec, db, num, index);
    		if (listRec!=null&&listRec.size()!=0) {
    			listReturn=listRec;
    		}
    		
    		
    		index++;
    		//须要依据新的list。从序号为0開始依次作为组合中最小的
    		if (index+num+1>listLend.size()) {
    			num++;
    			index=0;
    		}
    		if (listReturn==null||listReturn.size()==0) {
    			 //继续迭代。添加组合的数量
    			listReturn=makeUp(listLend, db, num,index);
    		}
    	   
    		return listReturn;
    	}
    	/**
    	 * 组合遍历
    	 * @param listLend
    	 * @param listReturn
    	 * @param db
    	 * @param num
    	 * @param index
    	 * @return
    	 */
    	
    	public static List<Lend2match> traversal(List<Lend2match> listLend,List<Lend2match> listReturn,Double db ,int num,int index){
    		Double dbTmp=db;
    		for (int i = index; i < listLend.size()-1-num; i++) {
    			
    			db=db-listLend.get(index).getLendAmount();
    			if (db==0) {//正好匹配
    				listReturn.add(listLend.get(index));
    			}else if (db>0) {
    				int index1=i+1;
    				int num1=num-1;
    				listReturn=traversal(listLend,listReturn, db, num1, index1);
    				if (listReturn!=null&&listReturn.size()!=0) {
    					listReturn.add(listLend.get(index));
    				}else {
    					listReturn=null;
    				}
    			}else if (db<0) {
    				listReturn=null;
    			}	
    			db=dbTmp;
    		}
    		return listReturn;
    	}


  • 相关阅读:
    常见的行元素与块元素
    [转]SVN服务器部署并实现双机同步及禁止普通用户删除文件
    [转]Axure共享工程Shared Project(二):编辑修改和提交
    如何添加网络打印机
    [转]JSON 转换异常 死循环 There is a cycle in the hierarchy
    比较常用的Properties配置文件的使用方法示例
    解决Tomcat项目重复加载导致pemgen space内存溢出
    怎样批量删除.svn文件
    [转]前端工程师必须掌握的知识点
    Freemarker 使用
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7113146.html
Copyright © 2020-2023  润新知