力扣 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,表示程序正常结束
}
相关推荐
自动驾驶小卡7 小时前
boost::circular_buffer的使用方法简介
c++·boost·circular_buffer
Greedy Alg8 小时前
LeetCode 142. 环形链表 II
算法
睡不醒的kun8 小时前
leetcode算法刷题的第三十二天
数据结构·c++·算法·leetcode·职场和发展·贪心算法·动态规划
先做个垃圾出来………9 小时前
残差连接的概念与作用
人工智能·算法·机器学习·语言模型·自然语言处理
乔宕一11 小时前
stm32 链接脚本没有 .gcc_except_table 段也能支持 C++ 异常
c++·stm32·嵌入式硬件
SuperCandyXu11 小时前
P3205 [HNOI2010] 合唱队-普及+/提高
c++·算法·洛谷
_OP_CHEN11 小时前
数据结构(C语言篇):(十二)实现顺序结构二叉树——堆
c语言·数据结构·算法·二叉树·学习笔记··顺序结构二叉树
_君落羽_11 小时前
ARM寄存器以及异常处理
c++
Yingjun Mo11 小时前
1. 统计推断-基于神经网络与Langevin扩散的自适应潜变量建模与优化
人工智能·神经网络·算法·机器学习·概率论
free11 小时前
基于librdkafa C++客户端生产者发送数据失败问题处理#2
c++·kafka