39 组合总和

本文最后更新于:2022年4月9日 中午

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。

示例 1:

1
2
3
4
5
6
输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]

示例 2:

1
2
3
4
5
6
7
输入:candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]

提示:

  • 1 <= candidates.length <= 30
  • 1 <= candidates[i] <= 200
  • candidate 中的每个元素都是独一无二的。
  • 1 <= target <= 500

Solution

参考 @liuyubobobo@liweiwei1419

  • 回溯法

  • 避免重复路径

    遇到这一类相同元素不计算顺序的问题,我们在搜索的时候就需要 按某种顺序搜索。具体的做法是:每一次搜索的时候设置 下一轮搜索的起点 begin

    img

从每一层的第 2 个结点开始,都不能再搜索产生同一层结点已经使用过的 candidate 里的元素。

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
28
29
// @lc code=start
class Solution {
private:
vector<vector<int>> res;

void dfs(const vector<int>& candidates, int index, int target, vector<int>& cur){
if(target==0){
res.push_back(cur);
return;
}

for(int i=index; i<candidates.size(); ++i){
if(target >= candidates[i]){
cur.push_back(candidates[i]);
dfs(candidates, i, target-candidates[i], cur);
cur.pop_back();
}
}
return;
}

public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<int> cur;
dfs(candidates, 0, target, cur);
return res;
}
};
// @lc code=end

补充:

什么时候使用 used 数组,什么时候使用 begin 变量:

  • 排列问题,讲究顺序(即 [2, 2, 3] 与 [2, 3, 2] 视为不同列表时),需要记录哪些数字已经使用过,此时用 used 数组;
  • 组合问题子集问题,不讲究顺序(即 [2, 2, 3] 与 [2, 3, 2] 视为相同列表时),需要按照某种顺序搜索,此时使用 begin 变量。

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!