力扣 77题 组合 记录

题目描述

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]]

思路

回溯三部曲:

  1. 确定回溯函数的返回值和参数
  2. 确定回溯的终止条件
  3. 确定回溯搜索的遍历过程

输入 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,表示程序正常结束
}
相关推荐
wuminyu11 分钟前
Kafka中sendfile与mmap实现机制解析
java·linux·c语言·jvm·c++
GreenTea1 小时前
vLLM 与 SGLang KV Cache 底层实现机制深度调研报告
前端·后端·算法
Bode_20021 小时前
多资源规划(含生产调度、库存管理及产能规划)的创新优化算法
算法·调度
土司大王2 小时前
LeetCode hot100——35.搜索插入位置:Java 二分模板、左闭右开区间与插入点分析
java·算法·leetcode
微三云生态系统架构师-彭丹3 小时前
远方好物S2B2C系统架构:一级分销与保证金托管的合规技术实现
人工智能·算法
土司大王3 小时前
LeetCode hot100——34.在排序数组中查找元素的第一个和最后一个位置:Java 二分模板、边界分析
java·算法·leetcode
罗西的思考4 小时前
机器人模型(WM / WAM / VLA)综合分析与对比:从「看」到「想」再到「做」
人工智能·算法·机器学习
无小道5 小时前
C++——列表初始化
c++·列表初始化
小哈里5 小时前
【知识】从学科到实践:自然・工程・社科・人文|算法・研发・产品・品牌设计
程序人生·算法·产品·设计·工程
blueSatchel5 小时前
c++action 编写(ros-humble)
c++·ros2