Given a set of candidate numbers (candidates
) (without duplicates) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sums to target
.
The same repeated number may be chosen from candidates
unlimited number of times.
Note:
- All numbers (including
target
) will be positive integers. - The solution set must not contain duplicate combinations.
Example 1:
Input: candidates =[2,3,6,7],
target =7
, A solution set is: [ [7], [2,2,3] ]
Example 2:
Input: candidates = [2,3,5],
target = 8,
A solution set is:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
对于一个给出的数target和一个数集C,问存在多少种不同的方案,使得可以从数集C中选出若干个数(每个数可以选择无限次)使得这些数的和等于target。
新题中没有:
- Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
如果有这个要求就要对数组C排序,使用过的就不能在使用了,因为会要保证大小顺序。
解法:递归 + backtracking, 注意数组的mutable.
Java:
public class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
if (candidates == null) return res;
Arrays.sort(candidates);
getCombinations(res, new ArrayList<>(), candidates, target, 0);
return res;
}
private void getCombinations(List<List<Integer>> res, List<Integer> list, int[] nums, int target, int pos) {
if (target < 0) return;
if (target == 0) {
res.add(new ArrayList<>(list));
return;
}
for (int i = pos; i < nums.length; i++) {
if (nums[i] > target) break;
if (i > pos && nums[i] == nums[i - 1]) continue;
list.add(nums[i]);
getCombinations(res, list, nums, target - nums[i], i);
list.remove(list.size() - 1);
}
}
}
Python:
class Solution:
# @param candidates, a list of integers
# @param target, integer
# @return a list of lists of integers
def combinationSum(self, candidates, target):
result = []
self.combinationSumRecu(sorted(candidates), result, 0, [], target)
return result
def combinationSumRecu(self, candidates, result, start, intermediate, target):
if target == 0:
result.append(list(intermediate))
while start < len(candidates) and candidates[start] <= target:
intermediate.append(candidates[start])
self.combinationSumRecu(candidates, result, start, intermediate, target - candidates[start])
intermediate.pop()
start += 1
Python: wo
class Solution(object):
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
res = []
self.helper(res, sorted(candidates), [], 0, 0, target)
return res
def helper(self, res, candidates, cur, temp, pos, target):
if temp > target:
return
if temp == target:
res.append(cur)
for i in range(pos, len(candidates)):
self.helper(res, candidates, cur + [candidates[i]], temp + candidates[i], i, target)
C++:
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
// 注意candidates不是有序的,要先排序处理
sort(candidates.begin(), candidates.end());
// 用以记录答案和当前方案
vector<vector<int>> ans;
vector<int> current;
// 开始回溯搜索
backtracking(ans, candidates, current, 0, target);
// 返回答案
return ans;
}
void backtracking(vector<vector<int>>& ans, vector<int>& candidates, vector<int> current, int last_use, int rest_target) {
// 当rest_target等于0时,说明已经找到了一组合法的方案
if (rest_target == 0) {
// 故将其加入到答案当中
ans.push_back(current);
}
// 否则就枚举下一个加入到current中的数,在枚举中注意2个条件
// i >= last_use,保证current是非递减的
// candidates[i] <= rest_target,保证rest_target不小于0
for (int i = last_use; i < candidates.size() && candidates[i] <= rest_target; i++) {
// 放入current中
current.push_back(candidates[i]);
// 继续搜索下一个数字
backtracking(ans, candidates, current, i, rest_target - candidates[i]);
// 回溯处理
current.pop_back();
}
}
};
类似题目:
[LeetCode] 40. Combination Sum II 组合之和 II
[LeetCode] 216. Combination Sum III 组合之和 III
[LeetCode] 377. Combination Sum IV 组合之和 IV
[LeetCode] 90. Subsets II 子集合 II
[LeetCode] 46. Permutations 全排列
[LeetCode] 47. Permutations II 全排列 II
[LeetCode] 131. Palindrome Partitioning 回文分割
All LeetCode Questions List 题目汇总