本文分析力扣的39组合总和以及40组合总和2
首先组合总和1并不难,只需要牢记在for循环的外面控制的是树层的横向移动,而for循环内则控制的是树枝的纵向移动。
那么接下来就来详细分析如何控制,第一所有回溯问题都可以抽象为一课树结构,那么分析本题可知节点都有可能为“果实”。
接下来控制树层的横向移动:
if(sum>target){
return
}
收获果实:
if(sum===target){
res.push([...path])
return
}
纵向移动使用for循环以及回溯,注意若sum大于则没必要再往下移动
for(let i=starthindex;i<candidates.length&&sum+candidates[i]<=target;i++){
sum+=candidates[i]
path.push(candidates[i])
backstracking(i,sum)
sum-=candidates[i]
path.pop(candidates[i])
}
最后返回res即可
完整代码:
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function(candidates, target) {
candidates=candidates.sort((a,b)=>a-b)
let res =[]
let path=[]
function backstracking(starthindex,sum){
if(sum===target){
res.push([...path])
return
}
if(sum>target){
return
}
for(let i=starthindex;i<candidates.length&&sum+candidates[i]<=target;i++){
sum+=candidates[i]
path.push(candidates[i])
backstracking(i,sum)
sum-=candidates[i]
path.pop(candidates[i])
}
}
backstracking(0,0)
return res
};
接下来看组合总和2.
2和1的主要区别显而易见,我们要对其进行树层去重,那么按上面的理论来讲我们应该在for循环外进行操作。但由于要排除前后相同又在一组内的合法情况所以需要在for循环内操作
if(i>statindex&&candidates[i]===candidates[i-1]){
continue//除了第一次进来会执行后面的代码,否则其余情况都不会执行
}
完整代码:
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum2 = function(candidates, target) {
let path=[],res=[]
candidates=candidates.sort((a,b)=>a-b)
backtracking(0,0)
return res
function backtracking(statindex,sum){
if(sum===target){
res.push([...path])
return
}
for(let i=statindex;i<candidates.length&&sum+candidates[i]<=target;i++){
if(i>statindex&&candidates[i]===candidates[i-1]){
continue
}
path.push(candidates[i])
sum+=candidates[i]
backtracking(i+1,sum)
path.pop()
sum-=candidates[i]
}
}
};