算法:从一组数集合里搜索,和为目标值得方案集

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

如有疑问,或不对的地方,谢谢留言指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值