给定一个数组 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 += currentNumused[i] = truebackTracking(i+1,sum)sum -= currentNumpath.pop()used[i] = false}}backTracking(0,0)return res}console.log(combinationSum())
}