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

题目描述

给定两个整数 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 <= 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 后返回;
    • 核心流程(从大到小枚举 + 回溯):① 遍历从 n 到 1 的所有数字 i(从大到小选,避免重复组合,比如不会同时出现 3,4 和 4,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;
    }
};
相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218613 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法