Leetcode刷题详解——组合

1. 题目链接:77. 组合

2. 题目描述:

给定两个整数 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

3. 解法(回溯):

3.1 算法思路:

题目要求我们从1到n中选择k个数的所有组合,其中不考虑顺序。也就是说[1,2]和[2,1]等价。我们s需要找出所有的组合,但不能重复计算相同元素的不同顺序的组合。对于选择组合,我们需要进行以下流程:

  1. 所有元素分别作为首位元素进行处理
  2. 在之后的位置上同理,选择所有元素分别作为当前位置元素进行处理
  3. 为避免计算重复组合,规定选择之后位置的元素时必须比前一个元素大,这样就不会有重复的组合

3.2 实现方法:

  1. 定义一个二维数组和一个一维数组。二维数组用来记录所有组合,一维数组用来记录当前状态下的组合
  2. 遍历1到n-k+1,以当前数作为组合的首位元素进行递归(从n-k+1到n作为首元素时,组合中一定不会存在k个元素)
  3. 递归函数的参数为两个数组、当前步骤以及n和k,递归流程如下:
    1. 结束条件:当前组合中已经有k个元素,将当前组合存进二维数组并返回(剪枝:如果当前位置之后的所有元素放入组合也不能满足组合中存在k个元素,直接返回)
    2. 从当前位置的下一个元素开始遍历到n,将元素赋值到当前位置,递归下一个位置
      Leetcode刷题详解——组合_第1张图片

3.3 C++算法代码:

class Solution {
    vector path; // 用于存储当前路径的数组
    vector> ret; // 用于存储所有满足条件的路径的二维数组
    int n, k; // n表示元素个数,k表示每个组合中的元素个数

public:
    vector> combine(int _n, int _k) {
        n = _n; // 初始化元素个数
        k = _k; // 初始化每个组合中的元素个数
        dfs(1); // 从第一个元素开始进行深度优先搜索
        return ret; // 返回所有满足条件的路径
    }

    void dfs(int start) {
        if (path.size() == k) { // 如果当前路径的长度等于k,说明找到了一个满足条件的路径
            ret.push_back(path); // 将当前路径添加到结果集中
            return;
        }
        for (int i = start; i <= n; i++) { // 从start开始遍历到n
            path.push_back(i); // 将当前元素添加到路径中
            dfs(i + 1); // 继续搜索下一个元素
            path.pop_back(); // 回溯,将当前元素从路径中移除
        }
    }
};

你可能感兴趣的:(leetcode,算法,职场和发展)