leetcode之組合數(Combination Sum)

Combination Sum

//代碼1
public class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if(candidates.length == 0 || candidates == null) return result;
        Arrays.sort(candidates);
        List<Integer> list = new ArrayList<Integer>();
        helper(result, list, candidates, 0, target);
        return result;
    }

    private void helper(List<List<Integer>> result,
                        List<Integer> list,
                        int[] candidates,
                        int sum,
                        int target) {
        if(sum == target) {
            result.add(new ArrayList<Integer>(list));
            return;
        }

        for(int i = 0; i < candidates.length; i++) {//每層的循環都是從0開始,導致出現重複的組合
            if(sum + candidates[i] <= target) {
                list.add(candidates[i]);
                helper(result, list, candidates, sum + candidates[i], target);
                list.remove(list.size() - 1);
            }
            else
                break;
        }
    }
}

Your answer:[[2,2,3],[2,3,2],[3,2,2],[7]]
Expected answer:[[2,2,3],[7]]

//代碼2
public class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if(candidates.length == 0 || candidates == null) return result;
        Arrays.sort(candidates);
        List<Integer> list = new ArrayList<Integer>();
        helper(result, list, candidates, target, 0);
        return result;
    }

    private void helper(List<List<Integer>> result,
                        List<Integer> list,
                        int[] candidates,
                        int target,
                        int k) {
        if(target == 0) {
            result.add(new ArrayList<Integer>(list));
            return;
        }
        if(target > 0) {
            for(int i = k; i < candidates.length; i++) {
                if(target < candidates[i]) break;
                list.add(candidates[i]);
                helper(result, list, candidates, target - candidates[i], i);//兩處修改的地方
                list.remove(list.size() - 1);
            }
        }
    }
}

正解代碼2對代碼1做了2點優化:

  1. 每層循環從當前開始層數開始,防止出現重複組合;
  2. 傳入的參數由和改爲差值,這樣可防止在數值很大的情況下出現溢出的異常。

Combination Sum II

在回溯法中,如果要去除重複的元素,只需在for循環中加入一個條件判斷即可,這個條件判斷隱含了兩層意思:
1. 每一層的第一個元素無條件加入解空間樹
2. 這一層從第二個元素開始進行比較,若這個元素與前面元素相同,不應該加入解空間樹

public class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if(candidates.length == 0 || candidates == null) return result;
        Arrays.sort(candidates);
        List<Integer> list = new ArrayList<Integer>();
        helper(result, list, candidates, target, 0);
        return result;
    }

    private void helper(List<List<Integer>> result,
                        List<Integer> list,
                        int[] candidates,
                        int target,
                        int k) {
        if(target == 0) {
            result.add(new ArrayList<Integer>(list));
            return;
        }
        if(target > 0) {
            for(int i = k; i < candidates.length; i++) {
                if(target < candidates[i]) break;
                if(i > k && candidates[i] == candidates[i - 1]) continue;//多個一個判斷條件
                list.add(candidates[i]);
                helper(result, list, candidates, target - candidates[i], i + 1);//在代碼2中,這裏是i
                list.remove(list.size() - 1);
            }
        }
    }
}
發佈了98 篇原創文章 · 獲贊 41 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章