這幾天,公司排課有個功能,需要一個算法,需要從選課組找到一組能用的解。今天,把這個算法基本實現抽離出來。講一下自己的思路。 此算法的功能大意就是:從一組數中找到,和能爲目標的值的幾種組合。 例如: 目標數爲:8 一組數集:1,1,2,2,3,4,5,6,7,8,10 結果爲: [3, 2, 2, 1] [3, 2, 2, 1] [4, 2, 1, 1] [4, 2, 1, 1] [4, 2, 2] [4, 3, 1] [4, 3, 1] [5, 2, 1] [5, 2, 1] [5, 2, 1] [5, 2, 1] [5, 3] [6, 1, 1] [6, 2] [6, 2] [7, 1] [7, 1] [8] 注意:有同學可能看出有重複的,對,比如組合[7, 1]有兩個,因爲1在數集中有兩個,所以7與兩個1分別有一種組合。(重複的數據可以在算法中加邏輯,這裏先不說了!哈哈) 遞歸邏輯:咱們可以這麼想,首先,10,8,7,6,5,4,3,2,2,1,1從左到右一次遍歷找能組成8的數,看第一個數: 1.當大於8時,不符合條件,跳到下一個; 2.當等於8時,記錄當前方案,並跳到下一個; 3.當小於8時, (1)記錄當前數,並在接下來的數中,找尋能組成(8-當前數的差)的和; (2)記錄當前數,跳過下一個數,找尋能組成(8-當前數的差)的和。 循環以上操作。(注意:我這裏可能理解起來不如畫圖,我畫圖又太差,就先不畫了,以後練習好了再補上,哈哈哈) 代碼實現: import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Test { public static void main(String [] args) { Integer[] intArrays = {1,1,2,2,3,4,5,6,7,8,10}; List<Integer> list = new ArrayList<>(intArrays.length); Collections.addAll(list, intArrays); List<List<Integer>> results = searchSingle(8,list); for(List<Integer> result : results){ System.out.println(result); } } /** * 搜索result在list中,有多少種組合 * @param result * @param list * @return */ public static List<List<Integer>> searchSingle(int result, List<Integer> list){ List<List<Integer>> results = new ArrayList<>(); Collections.sort(list,new OrderComparator()); searchGroup(result, 0,list,results, new ArrayList<> ()); return results; } /** * * @param result 目標結果 * @param index 從集合list那個位置開始搜索 * @param list 源數據 * @param results 能組成目標結果的結果集 * @param resultList 中間結果 */ public static void searchGroup(int result, int index, List<Integer> list, List<List<Integer>> results, List<Integer> resultList){ if(index + 1 > list.size()){ return; } int flag = sum(resultList,list.get(index),result); if(0 == flag){ if(index < list.size()){ List<Integer> copyList = new ArrayList<>(resultList); searchGroup(result, index + 1, list,results,copyList); } resultList.add(list.get(index)); results.add(resultList); }else if (-1 == flag){ List<Integer> copyList = new ArrayList<>(resultList); searchGroup(result, index + 1, list, results, copyList); resultList.add(list.get(index)); searchGroup(result, index + 1, list, results, resultList); }else{ searchGroup(result, index + 1, list, results, resultList); } } /** * 判斷list中的元素和加上element的和與result的關係 * 1.如果等於result返回0, * 2.如果大於result返回1, * 3.如果小於result返回-1。 * @param list * @param element * @param result * @return */ public static int sum(List<Integer> list, int element, int result){ int sum = element; for(int temp : list){ sum += temp; } if(sum == result){ return 0; }else{ return sum > result ? 1 : -1; } } }
如有疑問,或不對的地方,謝謝留言指出。