1. 程式人生 > >組合總和

組合總和

給定一個無重複元素的陣列 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。

candidates 中的數字可以無限制重複被選取。

說明:

所有數字(包括 target)都是正整數。
解集不能包含重複的組合。
示例 1:

輸入: candidates = [2,3,6,7], target = 7,
所求解集為:
[
[7],
[2,2,3]
]
示例 2:

輸入: candidates = [2,3,5], target = 8,
所求解集為:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
方法:遞迴
思路:
1,首先對陣列進行排序,方便操作並且節省開支;
2,陣列[2,3,6,7],target = 7,定義一個存放臨時結果的list,每次需要從start元素開始,比如,先將2存入list,然後target就變成7-2=5,再將2放入list,target就變成5-2=3,再將2放入list,target就是3-2=1,然後再拿start位置元素還是2,但是2比1大,所以不行,那麼就將list最後一個元素2去掉,然後將下一個元素也就是3存入list,這時候target變成了0,滿足條件,將這個list存入結果集res裡面;
3,按照第二步所描述的過程,遞迴迭代這個陣列,將符合條件的元素組合全部拿到即可!

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<Integer> list = new ArrayList<>();//新建堆疊用來判斷
        List<List<Integer>> res = new ArrayList<>();//結果集
        if (candidates == null || candidates.length == 0)
            return res;
        combin(candidates, 0, target, list, res);
        return res;
    }
    //對陣列元素(已排序)進行逐個判斷以及加入結果集
    private void combin(int[] candidates, int start, int target,List<Integer> list, List<List<Integer>> res) {
        //剛好滿足則將結果存入結果集
        if (target == 0) {
            res.add(new ArrayList<>(list));
            return;
        }
        for (int i = start; i < candidates.length; i ++) {
            if (candidates[i] <= target) { //判斷是否已經大於target
                list.add(candidates[i]);//將第一個元素存入         
                combin(candidates, i, target -candidates[i] , list, res);//繼續判斷進棧元素
                list.remove(list.size() - 1);//不滿足則將最後一個元素移除,進棧新元素判斷
            }
        }         
    }
}

注意:對陣列先排序,然後可以判斷如果當前元素已經超出,那麼後續肯定全部超出,不必浪費時間,可以提升效率!