算法:從一組數集合裏搜索,和爲目標值得方案集

    這幾天,公司排課有個功能,需要一個算法,需要從選課組找到一組能用的解。今天,把這個算法基本實現抽離出來。講一下自己的思路。
此算法的功能大意就是:從一組數中找到,和能爲目標的值的幾種組合。
例如:
目標數爲: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;
        }
    }
}

如有疑問,或不對的地方,謝謝留言指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章