跳至主要內容

leetcode77.组合

张威大约 2 分钟数据结构与算法回溯算法

77.组合

77. 组合 - 力扣(LeetCode)open in new window

给定两个整数 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
class Solution {
public:
    void backtracking(int n, int k, int startindex, vector<int>& path, vector<vector<int>>& result) {
        if(path.size() == k) {
            result.push_back(path);
            return;
        }

        for(int i = startindex; i <= n; ++i) {
            path.push_back(i);
            backtracking(n, k, i + 1, path, result);
            path.pop_back();
        }
    }

    vector<vector<int>> combine(int n, int k) {
        vector<int> path;
        vector<vector<int>> result;

        backtracking(n, k, 1, path, result);
        return result;
    }
};

剪枝操作

class Solution {
public:
    void backtracking(int n, int k, int startindex, vector<int>& path, vector<vector<int>>& result) {
        if(path.size() == k) {
            result.push_back(path);
            return;
        }

        for(int i = startindex; i <= n - (k - path.size()) + 1; ++i) {
            path.push_back(i);
            backtracking(n, k, i + 1, path, result);
            path.pop_back();
        }
    }

    vector<vector<int>> combine(int n, int k) {
        vector<int> path;
        vector<vector<int>> result;

        backtracking(n, k, 1, path, result);
        return result;
    }
};

在这个回溯算法中,n - (k - path.size()) + 1 这个表达式用于确定当前迭代中 i 的上限。这个表达式的目的是确保在后续的递归调用中,我们仍然能够选取足够的元素(k 个)来填充 path,从而避免无效的递归。

让我们逐步分析这个表达式:

  1. 目标:我们想要从 n 个元素中选取 k 个元素的所有可能组合。
  2. 当前状态:在回溯的某一层,path 已经包含了一些元素(path.size() 个)。
  3. 剩余需求:为了完成一个完整的组合,我们还需要选取 k - path.size() 个元素。
  4. 避免无效递归:如果 i 太大,那么在后续的递归调用中,我们可能没有足够的元素来填充 path,导致产生无效的组合。因此,我们需要确定 i 的上限。

假设当前 i = startindex,并且我们想要确保在后续的递归调用中,至少还有 k - path.size() 个元素可供选择。那么,最大的 i 应该满足以下条件:

  • i + (k - path.size()) - 1 <= n

这个不等式确保从 i 开始,我们至少可以连续选择 k - path.size() 个元素(因为索引是从 ii + (k - path.size()) - 1)。

重新排列上述不等式,我们得到:

  • i <= n - (k - path.size()) + 1