和全排列不同的是不需要用flag记录每个元素是否使用过,循环每次都从 i + 1 开始,保证每个元素不被重复组合。 对于全排列来说,i每次都要从1开始,深度优先搜索。
class Solution {
public:
vector<vector<int>> ans;
void backtracking(vector<int> temp, int k, int n, int startIndex){
if(temp.size() == k){
ans.push_back(temp);
return;
}
// 剪枝,对于剩余数组长度不够组合出答案时,剪去多余分支。
for(int i = startIndex; i <= n - (k - path.size()) + 1; i++){
temp.push_back(i);
backtracking(temp, k, n, i + 1);
temp.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
vector<int> temp;
backtracking(temp, k, n, 1);
return ans;
}
};
顺便附上一个全排列的逻辑
void dfs(int u){
//结束条件
if(u == n){
//将路径添加到ans中
return;
}
//for循环代表当前节点的所有子节点
for(int i = 1; i<=n; i++){
if(!state[i]){
//改变状态
state[i] = true;
num[u] = i;
//深搜
dfs(u+1);
//恢复现场
state[i] = false;
}
}
}
class Solution {
public:
vector<vector<int>> ans;
vector<int> path;
void find(int n, int k, int startIndex, int sum){
if(sum > n) return;
if(path.size() == k){
if(sum == n)
ans.push_back(path);
return;
}
for(int i = startIndex; i <= 9 - (k - path.size()) + 1; i++){
path.push_back(i);
sum += i;
find(n, k, i + 1, sum);
sum -= i;
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
find(n, k, 1, 0);
return ans;
}
};