力扣 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,表示程序正常结束
}
相关推荐
XLYcmy23 分钟前
京东 算法实习一面 下+手撕
c++·python·llm·概率论·数据处理·训练·codebert
反转180度1 小时前
Qt 6 + C++17 实现 SFTP 批量部署:工业设备运维工具实战解析
运维·c++·qt
罗西的思考2 小时前
【Agent OS / AIOS】AOHP 深度解读:当 OS 开始为 Agent 而设计
人工智能·算法·机器学习
民乐团扒谱机2 小时前
【微实验】组合优化matlab实战(马科维茨投资模型):在收益与风险之间,寻找最优的人生配比
大数据·人工智能·算法·机器学习·数学建模·matlab·组合优化
码匠许师傅2 小时前
【C++ 面试真题】聊聊 C++ 的多继承与虚继承
开发语言·c++·面试
Nil2083 小时前
leetcode 160相交链表
算法·leetcode·链表
迷途之人不知返4 小时前
算法系列2:滑动窗口
算法
有点。4 小时前
C++认识数
开发语言·c++
Herbert_hwt4 小时前
C语言零基础入门:循环控制与数据类型详解
c语言·数据结构·算法
2023自学中5 小时前
Qt 简易聊天室(第二篇),单线程 改为 多线程,方便后续增加文件传输功能
c++·qt