1、组合
问题描述
给定两个整数n
和k
,返回1 ... n
中所有可能的 k
个数的组合。
示例:
输入: n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
解题思路
- 该题目使用 回溯(su)法也等价于树(图)的深度优先遍历算法来求解。
- 分别定义用于存储最终结果的二维
vector
容器和存储每个结点的一维vector
容器。二维容器用于将每次一维容器装满元素后的压入。而大小为k
的一维容器用于装大小为k
的个数的组合。当数量满足为k
的时候,压入到二维容器中。 - 核心思想是图的深度优先遍历。当一维容器大小满足
k
个时,需要结点回退,重新将下一个新的元素压入一维容器中。再加上for
循环,可以保证遍历到所有符合情况且不重复的元素。 - 考虑到
k
值问题,在遍历过程中,n
个结点剩余小于k
个结点没有遍历时,可以停止遍历,因为此时已不满足k
个元素成为一个新的结点压入到二维数组中。这是一种剪枝的思想。
代码实现(1)
class Solution {
public:
vector< vector<int> > res; // 存放符合条件结果的集合
vector<int> path; // 用来存放符合条件结果
void backtracking(int startIndex, int n, int k) {
if (path.size() == k) {
res.push_back(path);
return;
}
// 这个for循环有讲究,组合的时候 要用startIndex,排列的时候就要从0开始
for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) {
path.push_back(i); // 处理节点
backtracking(i + 1, n, k);
path.pop_back(); // 回溯,撤销处理的节点
}
}
vector<vector<int>> combine(int n, int k) {
backtracking(1, n, k);
return res;
}
};
运行截图
代码实现(2)
- 下述代码和上面的代码思想是一致的。
class Solution {
public:
vector< vector<int> > ans;
vector<int> temp;
void deepFirstTraverse(int index, int n, int k){
if(temp.size() == k){
ans.push_back(temp);
return;
}
if(temp.size() + (n - index + 1) < k)
return;
temp.push_back(index);
deepFirstTraverse(index + 1, n, k);
temp.pop_back();
deepFirstTraverse(index + 1, n, k);
}
vector<vector<int>> combine(int n, int k) {
deepFirstTraverse(1, n, k);
return ans;
}
};
运行截图
2、组合综合
问题描述
给定一个无重复元素的数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为target
的组合。
candidates
中的数字