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] ]
題目標簽:Array
題目給了我們一個candidates array 和一個 target, 讓我們從array 里找到所有的組合,它的和是等於target的。任何組合只要是它的和等於target的話,都需要找到,但是不需要重復的。這道題中是可以重復利用一個數字的,那么我們就需要每次都代入同一個數字,直到它之和達到target 或者它超過了target, 然后在倒退回去一個數字,繼續找下一個數字,這種情況肯定是要用遞歸了。這里是backtracking,每次倒退回一個數字,需要繼續遞歸下去,在倒退,一直重復直到搜索了所有的可能性。
我們可以看原題中的例子:
[2,3,6,7] target 7
2 選2,sum = 2
2+2 選2,sum = 4
2+2+2 選2,sum = 6
2+2+2+2 選2,sum = 8 這時候 sum已經超出target,需要返回到上一個數字
2+2+2+3 選3,sum = 9, 也超出了target, 這里我們可以發現,如果是sorted array的話,從小到大,只要一次超出,后面的數字必然也會超出target,所以可以在第一次超出的時候就直接跳出這一個迭代
2+2+3 選3,sum = 7,等於target, 此時返回並且跳出這一個迭代,因為后面的數字肯定超出(array里不會有重復的數字)
2+3 選3,sum = 5,小於target,繼續遞歸同一個數字
2+3+3 選3,sum = 8,超出target,返回上一個數字
2+6 選6,sum = 8,超出target,返回上一個數字
3 選3,這里繼續從3開始遞歸
...
...
...
我們可以看出,一開始有一個迭代從2,一直到7,然后把每一個數字遞歸下去,包括它自己,每次遞歸下去的數字,會繼續有一個迭代,一旦超出或者等於了,返回前面一個數字繼續遞歸。所以把array sort一下就可以提早跳出那一輪的迭代。
具體看下面代碼。
Java Solution:
Runtime beats 97.14%
完成日期:07/16/2017
關鍵詞:Array
關鍵點:Backtracking with sorted array
1 public class Solution 2 { 3 public List<List<Integer>> combinationSum(int[] candidates, int target) 4 { 5 List<List<Integer>> list = new ArrayList<>(); 6 Arrays.sort(candidates); 7 backtrack(list, new ArrayList<>(), candidates, target, 0); 8 9 return list; 10 } 11 12 public static boolean backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums, int remain, int start) 13 { 14 if(remain < 0) // if remain is 0 or less than 0, meaning the rest numbers are even greater 15 return false; // therefore, no need to continue the loop, return false 16 else if(remain == 0) 17 { 18 list.add(new ArrayList<>(tempList)); 19 return false; 20 } 21 else 22 { 23 for(int i=start; i<nums.length; i++) 24 { 25 boolean flag; 26 tempList.add(nums[i]); 27 flag = backtrack(list, tempList, nums, remain - nums[i], i); // not i + 1 because we can use same number. 28 tempList.remove(tempList.size() - 1); 29 30 if(!flag) // if find a sum or fail to find a sum, there is no need to continue 31 break;// because it is a sorted array with no duplicates, the rest numbers are even greater. 32 } 33 34 return true; // return true because previous tempList didn't find a sum or fail a sum 35 } 36 } 37 }
參考資料:
https://leetcode.com/problems/combination-sum/#/discuss
LeetCode 算法題目列表 - LeetCode Algorithms Questions List