回溯模板
void backtracking (参数){
if (终止条件){
存放结果;
return ;
}
for (选择:本层集合中的元素(树中节点孩子的数量就是集合大小)){
处理节点;
backtracking(路径,选择列表); //递归
回溯,撤销处理结果;
}
}
class Solution {
public:
vector<int> curPath;
vector<vector<int>> result;
void BackTracking(int n, int k, int resIndex){
if (curPath.size()==k) {
result.push_back(curPath);
return ;
}
for (int i=resIndex; i<n+1; i++){
curPath.push_back(i);//将当前元素加入路径
BackTracking(n, k, i+1);//将当前路径和剩下的元素递归
curPath.pop_back();//弹出当前元素,为加入下一个本层剩余元素准备
}
}
vector<vector<int>> combine(int n, int k) {
BackTracking(n, k, 1);
return result;
}
};
感觉还行,不是特别难,按照回溯三部曲可以写出来。不着急写形参,需要什么加什么。
剪枝
class Solution {
public:
vector<int> curPath;
vector<vector<int>> result;
void BackTracking(int n, int k, int resIndex){
if (curPath.size()==k) {
result.push_back(curPath);
return ;
}
for (int i=resIndex; i<=n+1-(k-curPath.size()); i++){
curPath.push_back(i);//将当前元素加入路径
BackTracking(n, k, i+1);//将当前路径和剩下的元素递归
curPath.pop_back();//弹出当前元素,为加入下一个本层剩余元素准备
}
}
vector<vector<int>> combine(int n, int k) {
BackTracking(n, k, 1);
return result;
}
};
主要的改动为这句话 for (int i=resIndex; i<=n+1-(k-curPath.size()); i++){
k-curPath.size()表示还需要加入几个元素可以达到path.size()=k的题干条件
如果n=4,k=2,则每一个curPath最多含有2个元素,如果当前curPath.SIZE()=1,则 i<=n+1-(k-curPath.size())即i<=4,含义就是不轮当前curPath中的元素是多少,如果加入的i<=4就能满足k=2的条件,即12,13,14,23,24,34
如果n=4,k=3 则i<=n+1-(k-curPath.size())即i<=4;如果curPath=0, 则放入curPath的元素至少要小于等于n+1-(k-curPath.size())=2才能满足k=3的条件,比如123,124,134,234,很明显从三及以上开始比如34不满足。