组合总和
Question
给你一个 无重复元素 的整数数组 candidates
和一个目标整数 target
,找出 candidates
中可以使数字和为目标数 target
的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates
中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target
的不同组合数少于 150 个。
思路

根据之前的组合总和III的代码,稍加修改就可以实现
js
var combinationSum = function(candidates, target) {
const res = [] // 结果[][]
const path = [] // 每次递归的结果[]
let sum = target
const backtracking = ()=>{
if (sum < 0) { // 剪枝操作
return; // 如果path.size() == k 但sum != n 直接返回
}
if( sum===0 ){ //终止条件
res.push([...path])
return
}
for(let i=0; i< candidates.length ; i++){ // 本层集合中元素
path.push(candidates[i])
sum-= candidates[i]
backtracking()
path.pop()
sum+= candidates[i]
}
}
backtracking()
return res
};
此时有一个问题:结果集中存在一些重复的结果

如何解决呢?添加一个startIndex
变量
js
var combinationSum = function(candidates, target) {
const res = [] // 结果[][]
const path = [] // 每次递归的结果[]
let sum = target
// startIndex :每次递归的起使位置
const backtracking = (startIndex)=>{
if (sum < 0) { // 剪枝操作
return; // 如果path.size() == k 但sum != n 直接返回
}
if( sum===0 ){ //终止条件
res.push([...path])
return
}
for(let i=startIndex; i< candidates.length ; i++){ // 本层集合中元素
path.push(candidates[i])
sum-= candidates[i]
backtracking(i)
path.pop()
sum+= candidates[i]
}
}
backtracking(0)
return res
};
剪枝优化

如果下一层的sum(就是本层的 sum + candidates[i])已经大于target,就可以结束本轮for循环的遍历。
js
var combinationSum = function(candidates, target) {
const res = [] // 结果[][]
const path = [] // 每次递归的结果[]
let sum = target
// startIndex :每次递归的起使位置
const backtracking = (startIndex)=>{
if (sum < 0) { // 剪枝操作
return; // 如果path.size() == k 但sum != n 直接返回
}
if( sum===0 ){ //终止条件
res.push([...path])
return
}
for(let i=startIndex; i< candidates.length; i++){ // 本层集合中元素
if(sum-candidates[i] < 0 ) continue //剪枝优化
path.push(candidates[i])
sum-= candidates[i]
backtracking(i)
path.pop()
sum+= candidates[i]
}
}
backtracking(0)
return res
};