1. 程式人生 > 其它 >leetcode 39. 組合總和

leetcode 39. 組合總和

一、題目

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

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

說明:

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

二、解法

思路:回溯法。
要點:

  1. 巢狀陣列的初始化: List<List<Type>> ans=new ArrayList<List<Type>>()
  2. 對於函式引數的型別來說,List<Type>ArrayList<Type> 是不同的型別
  3. 陣列的拷貝:由於回溯法中的陣列 cur
    是時刻變化的,必須要拷貝後加入到 ans 中,問題就在於不能使用 clone() 函式( List 沒有該介面,是 ArrayList 中有的介面,所以 List<T> cur=new ArrayList<T>() 是不能使用該函式的)。可以採用建構函式的方式進行拷貝: new ArrayList<T>(cur)
  4. 為了剪枝更高效,使用排序,直接拋棄後面比 target 大的所有元素。
class Solution {
    void backtrace(List<List<Integer>> ans,int[] candidates,int target,List<Integer> cur,int idx){
        if(idx==candidates.length) return;
        if(target==0){
            ans.add(new ArrayList<Integer>(cur));
            return;
        }
        if(target>=candidates[idx]){
            // not choose current element
            backtrace(ans,candidates,target,cur,idx+1);
            // choose current element
            cur.add(candidates[idx]);
            backtrace(ans,candidates,target-candidates[idx],cur,idx);
            cur.remove(cur.size()-1);
        }
    }
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> ans=new ArrayList<List<Integer>>();
        List<Integer> cur=new ArrayList<Integer>();
        backtrace(ans,candidates,target,cur,0);
        return ans;
    }
}