力扣 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,表示程序正常结束
}
相关推荐
zero_one_Machel7 分钟前
leetcode73矩阵置零
算法·leetcode·矩阵
BeyondESH33 分钟前
Linux线程同步—竞态条件和互斥锁(C语言)
linux·服务器·c++
青椒大仙KI1138 分钟前
24/9/19 算法笔记 kaggle BankChurn数据分类
笔记·算法·分类
^^为欢几何^^42 分钟前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
豆浩宇42 分钟前
Halcon OCR检测 免训练版
c++·人工智能·opencv·算法·计算机视觉·ocr
WG_171 小时前
C++多态
开发语言·c++·面试
浅念同学1 小时前
算法.图论-并查集上
java·算法·图论
何不遗憾呢1 小时前
每日刷题(算法)
算法
立志成为coding大牛的菜鸟.1 小时前
力扣1143-最长公共子序列(Java详细题解)
java·算法·leetcode
鱼跃鹰飞1 小时前
Leetcode面试经典150题-130.被围绕的区域
java·算法·leetcode·面试·职场和发展·深度优先