标签:回溯 中等
# 题目
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]
1
2
3
4
5
6
2
3
4
5
6
提示:
- 1 <= candidates.length <= 100
- 1 <= candidates[i] <= 50
- 1 <= target <= 30
# 题解
题目特点:
- 取同一集合中的数组成一个组合
- 所给的数组中有重复的数,但是组合不能重复
这一题与组合问题最大的区别就是数组中有重复出现的数,但是要求组合不能重复,有两种办法:
- 按之前的思路求出所有组合,然后对组合进行去重
- 在找组合的过程中就实现去重的效果
第一种过于麻烦,因为每一个组合都是使用数组存储的,且组合一样,但是组合中的数在数组中的顺序不一样,很麻烦;
第二种就是先对给定的数组集合进行排序,让相同数字放在一起,然后控制循环过程中,如果出现同一数字,就跳过,以免重复
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum2 = function(candidates, target) {
const res = [], temp = [];
let sum = 0;
candidates.sort((a, b) => a - b); // 给candidates排序,让相同的数字在一块,后面好判断同一层是否组合重复了
function backtracing(startIndex) {
if(sum === target) {
res.push(Array.from(temp));
return ;
}
for(let i=startIndex; i<candidates.length && sum+candidates[i]<=target; i++) {
// 要对同一树层使用过的元素进行跳过
if(i>startIndex && candidates[i]===candidates[i-1]) continue;
sum += candidates[i];
temp.push(candidates[i]);
backtracing(i+1);
temp.pop();
sum -= candidates[i];
}
}
backtracing(0);
return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27