1. 程式人生 > 其它 >回溯——39. 組合總和

回溯——39. 組合總和

前幾題回溯,都是能明確知道回溯樹的depth,因此終止條件是:

1 if (path.size() == k) {
2     if (符合題目要求) {
3         result.add((ArrayList) path.clone()); 
4     }
5 }

這一題的要求只是:

  1. 和為target
  2. 唯一組合
  3. 資料可重複

因此最簡單的想法如下:

 1     private void backtracking(int[] candidates, int target, int startIndex, int sum) {
 2         if (sum == target) {
3 result.add((ArrayList) path.clone()); 4 } 5 6 //每次回溯的起點都是當前元素 7 for (int i = startIndex; i < candidates.length; ++i) { 8 path.add(candidates[i]); 9 //更新階段總和sum 10 backtracking(candidates, target, i, sum+candidates[i]);
11 path.remove(path.size() - 1); 12 } 13 }

但是跑樣例就已經報棧溢位的錯誤。因此尋求剪枝。

將原陣列先排序,使用

  Arrays.sort() 時間開銷僅為nlogn,這樣陣列就是非降序陣列。在遍歷回溯樹的過程中,對於下一個數的選擇,可以判斷其值+當前總和sum是否<=target,若不符合則不可能總和最後==target(陣列中所有元素為正整數)
    private void backtracking(int[] candidates, int target, int startIndex, int
sum) { if (sum == target) { result.add((ArrayList) path.clone()); } //path中的下一個元素必須 <= target - sum,否則在有序正整數陣列中將不可能達成sum == target for (int i = startIndex; i < candidates.length && candidates[i] <= target - sum; ++i) { path.add(candidates[i]); backtracking(candidates, target, i, sum+candidates[i]); path.remove(path.size() - 1); } }