题目描述
cpp
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
示例 1:
输入:n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
示例 2:
输入:n = 1, k = 1
输出:[[1]]
思路
回溯三部曲:
- 确定回溯函数的返回值和参数
- 确定回溯的终止条件
- 确定回溯搜索的遍历过程
输入 n = 4 和 k = 2:
初始调用:backtrack(result, combination, 4, 2, 1)
i = 1:
- 组合为 [1]。
- 递归调用 backtrack(result, combination, 4, 2, 2)。
i = 2:
- 组合为 [1, 2]。
- 组合达到长度 k,加入结果。
- 回溯到 [1]。
继续递归:
- i = 3:组合为 [1, 3],加入结果。
- i = 4:组合为 [1, 4],加入结果。
- 回溯到空组合。
i = 2:
- 组合为 [2]。
- 递归调用 backtrack(result, combination, 4, 2, 3)。
继续递归:
- i = 3:组合为 [2, 3],加入结果。
- i = 4:组合为 [2, 4],加入结果。
- 回溯到空组合。
i = 3:
- 组合为 [3]。
- 递归调用 backtrack(result, combination, 4, 2, 4)。
i = 4:
- 组合为 [3, 4],加入结果。
- 回溯到空组合。
i = 4:
- 组合为 [4]。
- 递归调用 backtrack(result, combination, 4, 2, 5)。
终止递归:
- 超出范围,没有更多元素可选,递归结束。
完整代码
cpp
#include<iostream>
#include<vector>
using namespace std;
// 定义一个名为 Solution 的类
class Solution {
private:
// 定义一个二维向量 result 来存储所有组合的结果
vector<vector<int>> result;
// 定义一个一维向量 path 来存储当前递归路径中的组合
vector<int> path;
// 递归函数 backtracking,负责生成组合
void backtracking(int n, int k, int startIndex) {
// 如果 path 的大小等于 k,表示找到一个有效组合
if (path.size() == k) {
result.push_back(path); // 将当前组合加入到结果集中
return; // 返回,结束当前递归
}
// 从 startIndex 开始循环,尝试加入每个可能的数字
for (int i = startIndex; i <= n; i++) { // 从 1 到 n 的 n 个数,所以 n 也包括在内
path.push_back(i); // 将当前数字加入到组合路径中
backtracking(n, k, i + 1); // 递归调用,生成下一个数字的组合
path.pop_back(); // 回溯,移除最近加入的数字,尝试其他可能性
}
}
public:
// 定义一个公有函数 combine,负责初始化并调用递归函数
vector<vector<int>> combine(int n, int k) {
backtracking(n, k, 1); // 题目是给出从 1 到 n 的 n 个数,所以从 1 开始
return result; // 返回最终生成的组合结果
}
};
// 主函数,程序执行的入口
int main() {
int k, n;
cin >> n >> k; // 从标准输入中读取 n 和 k 的值
Solution s; // 创建 Solution 类的对象
vector<vector<int>> result = s.combine(n, k); // 调用 combine 函数,获取组合结果
// 遍历并输出每一个组合
for (const auto& combination : result) {
// const:指明 combination 是一个常量引用,意味着在循环内部不能修改 combination 指向的内容
// 使用引用而不是值传递可以避免复制元素,从而提高效率
cout << "[";
for (int i = 0; i < combination.size(); i++) {
cout << combination[i]; // 输出组合中的每一个元素
if (i != combination.size() - 1) // 如果不是最后一个元素,输出逗号
cout << ",";
}
cout << "]" << endl; // 输出组合结束的方括号和换行符
}
return 0; // 返回 0,表示程序正常结束
}