[LeetCode - 回溯] 39. Combination Sum

1 問題

Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

For example, given candidate set [2, 3, 6, 7] and target 7,
A solution set is:

[
  [7],
  [2, 2, 3]
]

2 分析

如果對輸入不做處理,所有可能出現的數字組合有 C1n+C2n+...+Cnn 種,將其中每一個與target比較,時間複雜度是指數級別的。
但是該問題蘊含着數字的大小、相等關係,因此需要利用這種內在的數字關係來提高算法的運行效率。
爲此,將輸入的數組進行排序,排序算法的時間複雜度是O(nlogn) 。排序之後,整個解法的計算過程如圖所示:
遞歸樹
設輸入的數組用 a1,a2,...,an 表示。上圖中,樹的結點表示所有可能與target相等的組合,層數等於可能的組合中的數字個數。令 Sn 表示每個節點中所有元素的和,因此:

  • 如果Sntarget 該節點存在子節點,繼續按照圖示規律訪問子節點;
  • 如果Sn>target ,該節點爲葉子,應當回溯回父節點。

在所有可能的組合遍歷完成後,與target相等的組合會被記錄下來。
該算法的時間複雜度爲樹中所有節點的數目,與題目所給輸入值有關。

3 代碼

遞歸+回溯:

public class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        getResult(result, new ArrayList<Integer>(), candidates, target, 0);
        return result;
    }

    private boolean getResult(List<List<Integer>> result, List<Integer> cur, int candidates[], int target, int start){
        if(target == 0){
            result.add(new ArrayList<Integer>(cur));
            return true;
        }else if(target < 0){
            return false;
        }else{
            for(int i = start; i < candidates.length && target >= candidates[i]; i++){
                cur.add(candidates[i]);
                boolean res = getResult(result, cur, candidates, target - candidates[i], i);
                if(!res){
                    return false;
                }
                cur.remove(cur.size() - 1);
            }
            return true;
        }
    }
}
發佈了81 篇原創文章 · 獲贊 8 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章