这几天,公司排课有个功能,需要一个算法,需要从选课组找到一组能用的解。今天,把这个算法基本实现抽离出来。讲一下自己的思路。 此算法的功能大意就是:从一组数中找到,和能为目标的值的几种组合。 例如: 目标数为: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; } } }
如有疑问,或不对的地方,谢谢留言指出。