leetcode77.组合
大约 2 分钟
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
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
,从而避免无效的递归。
让我们逐步分析这个表达式:
- 目标:我们想要从
n
个元素中选取k
个元素的所有可能组合。 - 当前状态:在回溯的某一层,
path
已经包含了一些元素(path.size()
个)。 - 剩余需求:为了完成一个完整的组合,我们还需要选取
k - path.size()
个元素。 - 避免无效递归:如果
i
太大,那么在后续的递归调用中,我们可能没有足够的元素来填充path
,导致产生无效的组合。因此,我们需要确定i
的上限。
假设当前 i = startindex
,并且我们想要确保在后续的递归调用中,至少还有 k - path.size()
个元素可供选择。那么,最大的 i
应该满足以下条件:
i + (k - path.size()) - 1 <= n
这个不等式确保从 i
开始,我们至少可以连续选择 k - path.size()
个元素(因为索引是从 i
到 i + (k - path.size()) - 1
)。
重新排列上述不等式,我们得到:
i <= n - (k - path.size()) + 1