LeetCode Combination Sum I,II,III,IV

介紹

LeetCode300題小目標達成
這是一類問題,都可以用backtrack(回溯法)來求,這裏放在一起比較一下異同。首先是Combination Sum I,問題:給定一個int數組,不包含重複數字,現在需要從裏面可重複地取出一些數使得它們的和爲target,返回所有不同的取法。這裏可以從兩個角度考慮:1.每次往arr裏面添加數據,比如添加1,那麼剩下的就是在數據集中找到和爲target-1的所有可能,並保存數據,如果最後的目標小於0,那麼返回,等於0則添加至list;2.同樣的每次添加數據,剩下的起點則從添加的數據開始,比如1,直到最終結果=target,則添加至list中。這裏爲了防止出現保存重複的結果,每次都從數組當前位置往後遍歷。(見代碼I中變量start)。

然後是Combination Sum II。和第一題不同的是,數組包含重複數字,但是不能重複取。方法大致不變,仍然是回溯法,但是這裏每次回溯的起始位置就需要變成start+1了。還有一點不同,這裏包含重複數據,爲了防止記錄重複的結果,這裏我們把數組先從小到大排序,並且用HashSet去除重複結果。代碼見下2。

最後是Combination Sum III。現在需要從1~9中選擇kk個不同的數字使得它們的和爲nn。這樣一來,限定了每個可能結果的長度,即是kk。不怕,我們在回溯中再添加一個變量,用於記錄當前結果的長度,或者直接用當前結果arr的長度來和目標kk比較,回溯的大致思路不變,只是每次回溯的判定和邊界條件發生變化。代碼見下3。

總結起來就是萬變不離其宗,我們想要求f(target),那麼我們就去嘗試先試着添加一個元素a,那麼剩下的結果就變成了求f(target-a),依次類推,直到最後爲0,這樣就算一次滿足條件的組合。

還有一道Combination Sum IV,不過這裏只要求滿足條件的個數,因此可以用DP來求解,代碼見下4。

Java代碼

Combination Sum I代碼:

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> list = new ArrayList();
        dfs(list, new ArrayList<Integer>(), candidates,target,0,0);
        return list;
    }
    public void dfs(List<List<Integer>> list, List<Integer> arr, int[] candidates, int target, int sum, int start){
        if(sum >target) return;
        if(sum==target){
            list.add( new ArrayList<>(arr));
            return;
        }
        else{
            for(int i=start;i<candidates.length;i++){
                arr.add(candidates[i]);
                dfs(list,arr,candidates,target,sum+candidates[i],i);
                arr.remove(arr.size()-1);
            }
        }
    }

Combination Sum II:

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> list = new ArrayList();
        Arrays.sort(candidates);
        dfs(list, new ArrayList<Integer>(), candidates,target,0,0);
        HashSet hs = new HashSet(list);
        list.clear();
        list.addAll(hs);
        return list;
    }
    public void dfs(List<List<Integer>> list, List<Integer> arr, int[] candidates, int target, int sum, int start){
        if(sum >target) return;
        if(sum==target){
            list.add( new ArrayList<>(arr));
            return;
        }
        else{
            for(int i=start;i<candidates.length;i++){
                arr.add(candidates[i]);
                dfs(list,arr,candidates,target,sum+candidates[i],i+1);
                arr.remove(arr.size()-1);
            }
        }
    }

Combination Sum III:

    public List<List<Integer>> combinationSum3(int k, int n) {
        List<List<Integer>> list = new ArrayList();
        dfs(list, new ArrayList<Integer>(), n, 1, k);
        return list;
    }
    public void dfs(List<List<Integer>> list, List<Integer> arr, int tar, int start, int num){
        if(tar<0||arr.size()>num) return;
        if(tar==0&&arr.size()==num){
            list.add(new ArrayList<>(arr));
            return;
        }
        else{
            for(int i=start;i<=tar&&i<=9;i++){
                arr.add(i);
                dfs(list,arr,tar-i,i+1,num);
                arr.remove(arr.size() - 1);
            }
        }
    }

Combination Sum IV:

    public int combinationSum4(int[] nums, int target) {
        int dp[] = new int[target+1];
        dp[0]=1;
        for(int i=1;i<=target;i++){
            for(int j=0;j<nums.length;j++){
                if(i>=nums[j]) dp[i] += dp[i-nums[j]];
            }
        }
        return dp[target];
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章