回溯——39. 組合總和
阿新 • • 發佈:2021-12-07
前幾題回溯,都是能明確知道回溯樹的depth,因此終止條件是:
1 if (path.size() == k) { 2 if (符合題目要求) { 3 result.add((ArrayList) path.clone()); 4 } 5 }
這一題的要求只是:
- 和為target
- 唯一組合
- 資料可重複
因此最簡單的想法如下:
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, intsum) { 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); } }