力扣 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,表示程序正常结束
}
相关推荐
程序员爱德华1 小时前
Python与C++:异同点对比
c++·python
普通攻击往后拉1 小时前
Leetcode 206. 反转链表
算法·leetcode·链表
@syh.2 小时前
【贪心】矩阵消除游戏
算法·游戏·矩阵
可编程芯片开发2 小时前
基于零极点配置的PID控制系统simulink建模与仿真
算法
徐小夕3 小时前
开源!我用SQLite + DuckDB打造了一款可视化AI问数平台
前端·算法·github
Hrain-AI3 小时前
2026 企业 AI 智能体平台横评:8 大主流平台 7 维度实测对比
人工智能·算法·机器学习
Angel Q.4 小时前
因子分析和生成模型有什么关系?从“幕后因素”到“生成数据”
算法
888CC++4 小时前
C语言与C++的区别:从面向过程到面向对象
java·c语言·c++
FBI HackerHarry浩5 小时前
AI大模型开发V2第四阶段线性回归
人工智能·算法·线性回归