回溯其实就是递归,这里很容易想到用多层for循环来暴力破解。改题的k=2就用两层for循环,k=n就用n层for循环,但是写代码写那么多for循环肯定不切实际。所以使用回溯法解决这个问题。
一层递归就是一层for循环
递归三部曲:
1、确定递归参数和返回值
2、确定终止条件
3、单层递归逻辑
代码如下:
vector<int> path;
vector<vector<int>> res;
void backtracking(int n, int k, int startindex) {
if (path.size() == k) {
res.push_back(path);
return;
}
for (int i = startindex; i <= n; ++i) {
path.push_back(i);
backtracking(n, k, i + 1);
path.pop_back(); // 重点,12,弹出2再13,弹出3再14,弹出41再23
}
}
vector<vector<int>> combine(int n, int k) {
backtracking(n, k, 1);
return res;
}
优化:剪枝操作
列表剩余元素 >= 所需元素数目
n - 1 >= k - path.size
for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置