39 Combination Sum 组合总和
Description:
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:
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]
]
题目描述:
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 :
示例 1:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:
输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
思路:
回溯法
- 先对 candidates排序, 保证数组从小到大排列
- 从 candidates中按大小顺序选出元素加入候选列表
- 如果 target == 0, 将候选列表加入到结果中
- 撤销选择
注意这里的元素可以无限重复选择, 所以选择下一层递归函数的时候要从相同下标开始选取
时间复杂度O(n!), 空间复杂度O(n)
代码:
C++:
class Solution
{
public:
vector> combinationSum(vector& candidates, int target)
{
vector> result;
vector temp;
sort(candidates.begin(), candidates.end());
trackback(result, candidates, target, 0, temp);
return result;
}
void trackback(vector> &result, vector &candidates, int target, int start, vector &temp)
{
if (target < 0) return;
if (target == 0) result.push_back(temp);
for (int i = start; i < candidates.size(); i++)
{
temp.push_back(candidates[i]);
trackback(result, candidates, target - candidates[i], i, temp);
temp.pop_back();
}
}
};
Java:
class Solution {
public List> combinationSum(int[] candidates, int target) {
List> result = new ArrayList<>();
Arrays.sort(candidates);
trackback(result, candidates, target, 0, new ArrayList<>());
return result;
}
private void trackback(List> result, int[] candidates, int target, int start, List list) {
if (target < 0) return;
if (target == 0) {
result.add(new ArrayList<>(list));
return;
}
for (int i = start; i < candidates.length; i++) {
list.add(candidates[i]);
trackback(result, candidates, target - candidates[i], i, list);
list.remove(list.size() - 1);
}
}
}
Python:
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
if not target:
return [[]]
elif not candidates or target < min(candidates):
return []
result = []
for i in candidates:
for j in self.combinationSum(list(filter(lambda x: x >= i, candidates)), target - i):
result.append([i] + j)
return result