day155—回溯—组合(LeetCode-77)

题目描述

给定两个整数 nk,返回范围 [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 <= n <= 20
  • 1 <= k <= n

解决方案:

这段代码的核心功能是生成从 1 到 n 的数字中选取 k 个数字的所有组合 (组合不考虑顺序,比如 n=4、k=2 时,输出 [[4,3],[4,2],[4,1],[3,2],[3,1],[2,1]]),采用「回溯 + 剪枝」的思路实现,是组合问题的经典高效解法。

核心逻辑

  1. 成员变量作用

    • path:临时数组,存储当前正在构造的组合(比如选取了 2 个数字时,path 可能是 4,3);
    • ans:最终结果数组,存储所有符合条件的 k 个数组合。
  2. 递归函数 dfs 逻辑

    • 参数 n:当前可选数字的上界(只能从 1~n 中选数);k:需要选取的数字个数;
    • 剪枝条件(提前终止无效递归):if(n < k - len) ------ 剩余可选数字个数(n)小于 "还需要选的数字个数(k-len)",说明不可能凑够 k 个数,直接返回,避免无效递归;
    • 终止条件:if(len == k) ------ 当前组合的长度等于 k,说明已选够 k 个数,将 path 加入 ans 后返回;
    • 核心流程(从大到小枚举 + 回溯):① 遍历从 n1 的所有数字 i(从大到小选,避免重复组合,比如不会同时出现 3,44,3);② 选数字 i:将 i 加入 path,递归调用 dfs(i-1, k)(下一轮只能从 1~i-1 中选数,保证组合内数字递减,无重复);③ 回溯:递归返回后,执行 path.pop_back() 删掉刚加入的数字,尝试下一个可选数字。
  3. 主函数 combine

    • 从数字上界 n 开始调用 dfs,启动组合构造过程;
    • 最终返回存储所有 k 数组合的 ans

关键特点

  • 剪枝优化:n < k - len 的判断是核心优化点,能大幅减少递归次数(比如 n=5、k=3,当前 path 长度为 1,还需选 2 个数,若剩余可选数字只有 1 个,直接终止);
  • 去重逻辑:从大到小枚举数字,且下一轮只能选更小的数字,天然保证组合内数字递减,避免生成重复组合(组合不考虑顺序,此逻辑符合组合的定义)。

总结

  1. 核心思路:递归枚举可选数字,从大到小选数避免重复组合,通过剪枝提前终止无效递归,回溯遍历所有合法的 k 数组合;
  2. 关键操作:path.push_back()(选数)和 path.pop_back()(回溯)是遍历所有组合的核心,剪枝条件是提升效率的关键;
  3. 功能效果:能输出 1~n 中选 k 个数的所有组合,无重复、无遗漏,且效率高于无剪枝的暴力枚举。

以 n=4、k=2 为例,最终会生成所有 2 数组合:[[4,3],[4,2],[4,1],[3,2],[3,1],[2,1]],符合组合的定义(不考虑顺序)。

函数源码:

cpp 复制代码
class Solution {
public:
    vector<int>path={};
    vector<vector<int>>ans={};

    void dfs(int n,int k){
        int len=path.size();
        if(n<k-len){
            return;
        }
        if(len==k){
            ans.push_back(path);
            return;
        }

        for(int i=n;i>0;i--){
            path.push_back(i);
            dfs(i-1,k);
            path.pop_back();
        }
    }

    vector<vector<int>> combine(int n, int k) {
        dfs(n,k);
        return ans;
    }
};
相关推荐
张欣-男18 分钟前
3分钟理解线性代数
线性代数·算法
白狐_79822 分钟前
408 数据结构|外部排序优化:怎么减少时间开销
数据结构·算法
小白说大模型23 分钟前
Hermes 全配置指南:从裸版到 AI Agent 天花板
大数据·人工智能·学习·算法·机器学习·数据挖掘
a1879272183133 分钟前
【算法】动态规划入门:从打家劫舍到状态设计的三堂课
算法·leetcode·动态规划·dp·回溯·暴力
淡海水10 小时前
07-04-并发-ConcurrentBag-T-工作窃取WorkStealing算法
开发语言·算法·c#·bag·concurrent·workstealing
leobertlan11 小时前
好玩系列:训练一个神经网络模型指导小孩玩游戏2-大局观教练
算法
Tisfy11 小时前
LeetCode 3876.构造奇偶一致的数组 II:三种情况分类讨论(其实还是脑筋急转弯)
算法·leetcode·题解·脑筋急转弯
乐迪信息12 小时前
智慧港口船舶AI算法实现在线状态监测
大数据·人工智能·深度学习·算法·计算机视觉
木井巳14 小时前
【BFS/DFS 解决 FloodFill 算法】太平洋大西洋水流问题
java·算法·leetcode·深度优先·广度优先·宽度优先·推荐算法
心抵鹊14 小时前
归并排序之翻转对(hard)
数据结构·算法