1. 程式人生 > >優化後的組合算法

優化後的組合算法

i++ 能夠 bsp n! ack nbsp rem 沒有 n的階乘

項目中一個算法中涉及到了組合,大概業務是:給定一個值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;
	}


優化後的組合算法