深搜练习(组合)(5)

一.题目

77. 组合 - 力扣(LeetCode)

二.思路讲解

2.1 思路讲解

本题要求从 [1, n] 中选出 k 个数的所有组合(无序 ,顺序不限)。我们可以画出决策树 :每一层决定是否选取当前数字,并向后推进,确保不重复。采用深度优先搜索(DFS) 回溯框架,用 pos 参数表示当前可以从哪个数字开始选取(每次只能选 ≥ pos 的数),这样能保证组合不重复。

递归终止条件 :当 path 长度达到 k 时,将当前组合加入结果集。

三.代码演示

cpp 复制代码
class Solution {
public:
    vector<int> path;
    vector<vector<int>> ret;
    vector<vector<int>> combine(int n, int k) 
    {
        dfs(n,k,1);
        return ret;
    }
    void dfs(int n,int k,int pos)
    {
        //1.合法的叶子节点
        if(path.size() == k)
        {
            ret.push_back(path);
            return;
        }
        for(int i = pos;i <= n;i++)
        {
            path.push_back(i);
            dfs(n,k,i+1);
            path.pop_back();
        }
    }
};

四.代码讲解

一、全局变量设计

为了实现回溯,我们定义两个成员变量

  • path:一维向量,记录当前正在构建的组合。

  • ret:二维向量,存储所有满足条件的组合结果。

这些变量在递归过程中共享状态,需要手动回溯。

二、主函数 combine

主函数接收两个整数 nk,调用递归函数 dfs(n, k, 1) 开始深度优先搜索,最后返回结果集 ret。初始 pos1,表示从数字 1 开始考虑。

三、递归函数 dfs

递归函数 dfs(int n, int k, int pos) 的含义是:当前已经构建了部分组合(存储在 path 中),接下来可以从 [pos, n] 中选择数字,目标是选出总共 k 个数。执行流程如下:

四、递归终止条件

path.size() == k 时,说明已经选满了 k 个数,得到一个有效组合,将其加入 ret 并返回。这是递归的出口

五、递归步骤分解

使用 for 循环,从 i = posi <= n,依次考虑每个数字:

  • i 加入 path 末尾。

  • 递归调用 dfs(n, k, i+1),表示下一个数字只能从 i+1 开始选择,从而保证了组合的无序性 (不会出现 [2,1][1,2] 重复)。

  • 递归返回后,执行回溯 :将 path 末尾的元素弹出,以便尝试下一个数字。

六、回溯与恢复现场

由于 path 是全局变量,不同分支共享状态,因此必须在递归返回后手动恢复现场,即弹出刚刚加入的数字。这是回溯算法的核心,确保后续选择不受干扰。

七、关键细节
  • pos 参数的作用 :每次递归只从 i+1 开始选择,保证了组合是不重复的(每个数字只用一次且顺序固定)。

  • 递归深度 :最大为 k,即组合的长度。

  • 剪枝优化 :当前代码未使用剪枝,但可以加入优化。例如,如果 path.size() + (n - pos + 1) < k,说明即使把后面所有数字都选上也不够 k 个,则可以直接 return,提前终止无效分支。这样能显著提高效率,尤其当 n 较大时。

  • 时间复杂度 :组合总数为 C(n, k),每个组合构建需要 O(k) 时间,总时间复杂度 O(k * C(n, k))

  • 空间复杂度:递归栈深度 O(k),加上存储结果的空间 O(k * C(n, k))。

相关推荐
小宋加油啊几秒前
机械臂抓取物体 PVN3D算法调研学习
学习·算法·3d
lqqjuly1 分钟前
前沿算法深度解析(一)
算法
小欣加油28 分钟前
leetcode1926 迷宫中离入口最近的出口
数据结构·c++·算法·leetcode·职场和发展
星恒随风1 小时前
C++ 类和对象入门(五):初始化列表、explicit 和 static 成员详解
开发语言·c++·笔记·学习·状态模式
浪客灿心2 小时前
项目篇:模块设计与实现
数据库·c++
牛油果子哥q2 小时前
【C++ STL vector】C++ STL vector 终极精讲:动态数组底层原理、两倍扩容机制、迭代器失效、增删查改、性能剖析与工程避坑指南
开发语言·c++
happymaker06263 小时前
LeetCodeHot100——42.接雨水
算法
阿正的梦工坊4 小时前
【Rust】07-错误处理:Option、Result 与 ? 运算符
开发语言·算法·rust
为何创造硅基生物4 小时前
独占指针的创建std::make_unique 本身自带堆出现
c++
kyle~4 小时前
ROS 2 与 Isaac Sim 联合仿真(一)体系架构、环境选型与基础通信闭环
c++·机器人·nvidia·仿真·ros2