给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明: 所有数字(包括目标数)都是正整数。解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
解题重点:集合(数组candidates)有重复元素,但还不能有重复的组合
解题思路:
1.组合问题抽象为树结构;
2.确定使用过的维度:“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上使用过,一个维度是同一树层上使用过;
3.题目中,元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同。所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。
// 回溯 - 组合求和
window.onload = function () {
const combinationSum = (candidates=[10,1,2,7,6,1,5], target=8) => {
const res = [],path=[]
candidates.sort((a,b)=>a-b)
//使用used【i】标记当前迭代的状态,是处在树层还是树枝
let used = new Array(candidates.length).fill(false)
const backTracking = (startIndex,sum) => {
if(sum === target){
res.push(Array.from(path))
return
}
for(let i = startIndex;i < candidates.length;i++){
let currentNum = candidates[i]
if(currentNum>target){break}
//如果和上一个值相同,且处于横向回溯的过程中,就跳出当前迭代
if(candidates[i] === candidates[i-1] && !used[i-1]){continue}
path.push(currentNum)
sum += currentNum
used[i] = true
backTracking(i+1,sum)
sum -= currentNum
path.pop()
used[i] = false
}
}
backTracking(0,0)
return res
}
console.log(combinationSum())
}