给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的数字可以无限制重复被选取。
说明:
- 所有数字(包括 target)都是正整数。
- 解集不能包含重复的组合。
解法1:递归,去重DFS,设置搜索起点。
class Solution {
public:
vector<int> candidates;
vector<vector<int> > res;
vector<int> path;
public:
void DFS(int start, int target, int depth) {
// 打印递归调试信息
for(int i=0;i<depth;i++) printf(" "); printf("DFS(%d, %d)", start, target);
printf(" ["); for(int i=0;i<path.size();i++) printf("%d ", path[i]); printf("]\n");
if (target == 0) {
res.push_back(path);
return;
}
// candidates排序后target<candidates[i]即可跳出循环,剪枝
for (int i = start; i < candidates.size() && target - candidates[i] >= 0; i++) {
path.push_back(candidates[i]);
// 为避免重复,设置搜索起点,设置depth是为了调试
DFS(i, target - candidates[i], depth+1);
path.pop_back();
}
}
vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
std::sort(candidates.begin(), candidates.end());
this->candidates = candidates;
DFS(0, target, 0);
return res;
}
};
int main()
{
int a[]={2,3,6,7}; vector<int> aa(a,a+4);
Solution *so = new Solution();
vector<vector<int> > v = so->combinationSum(aa, 7);
cout<<v.size()<<endl;
for(int i=0;i<v.size();i++){
for(int j=0;j<v[i].size();j++)
printf("%d ", v[i][j]);
printf("\n");
}
return 0;
}
输出:
DFS(0, 7) []
DFS(0, 5) [2 ]
DFS(0, 3) [2 2 ]
DFS(0, 1) [2 2 2 ]
DFS(1, 0) [2 2 3 ]
DFS(1, 2) [2 3 ]
DFS(1, 4) [3 ]
DFS(1, 1) [3 3 ]
DFS(2, 1) [6 ]
DFS(3, 0) [7 ]
2
2 2 3
7
解法2:递推