题目简述:从给定的数组中找出若干个数字,使这些数字之和等于target,不能包含重复的组合,每个元素只能只用一次
错误代码
下面的代码无法去重
var combinationSum2 = function (candidates, target) {
let res = []
candidates.sort((a, b) => a - b)
var backtrack = function (start, one, sum) {
if (sum === 0) {
res.push([...one])
return
}
if (sum < 0) return
for (let i = start; i < candidates.length; ++i) {
one.push(candidates[i])
backtrack(i + 1, one, sum - candidates[i])
one.pop()
}
}
backtrack(0, [], target)
return res
};
无法去重的测试用例
因为存在两个 1,导致下面的这个问题
再一个就是想到了使用set来去重,但是set存数组的话,是存取的数组的引用,所以也不能使用set来去重,如果实在想使用set的话,可以使用arr.join(',')来把数组变成字符串再存到set中
最终解决方案
重点就是 12 行
这里就要深刻的理解回溯了,这里就是产生的一棵树,那么for进行遍历的时候,是进行的同一层级的计算,那么就会跳过相同的元素
for 进行的是广度
for 里面的backtrack就是深度了,
var combinationSum2 = function (candidates, target) {
let res = []
candidates.sort((a, b) => a - b)
var backtrack = function (start, one, sum) {
if (sum === 0) {
res.push([...one])
return
}
if (sum < 0) return
for (let i = start; i < candidates.length; ++i) {
// 跳过同一层级中的形同元素, 同一层级 打重点
if (i > start && candidates[i] === candidates[i - 1]) continue
one.push(candidates[i])
backtrack(i + 1, one, sum - candidates[i])
one.pop()
}
}
backtrack(0, [], target)
return res
};