什么是回溯法?
一种回溯搜索法,属于纯暴力搜索。
解决的问题:组合、切割、子集、排列、棋盘
回溯法解决的问题都能抽象为树形结构
回溯法模版跟递归相似:
参数和输出:一般只要参数,不用输出;停止条件,:也是if语句,里面写存放结果和return ;;遍历历程:
组合
这里基本就是模版了。
参数:n,k和startindex,index作用为算是定位除i之后的数。
例如:i=1,加入path,之后递归,index=i+1,再添进path,此时{1,2},再递归,此时path长度等于k,
保存result,返回,返回后弹出2,然后再添加3,一个流程,4一个流程。至此i=1循环结束。i=2,3,4一样流程。
这是未剪枝版本。
public class Solution {
public IList<IList<int>> result = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> Combine(int n, int k) {
backtracking(n,k,1);
return result;
}
public void backtracking(int n,int k,int startindex){
if(path.Count == k){
result.Add(new List<int>(path));
return ;
}
for(int i=startindex;i<=n;i++){
path.Add(i);
backtracking(n,k,i+1);
path.RemoveAt(path.Count-1);
}
}
}
剪枝版本
修改for (int i = startIndex; i <= n - (k - path.Count) + 1; i++)
剪枝主要解决反复循环的问题,例如n=4,k=4;如果i<=n,那么每次递归和for循环会循环到已知不可能实现的部分,所以i<=n-(k-path.Count)+1可以达到剪枝下面是公式解释。
path.size() : 已经找的个数
k-path.size() :还需找的个数
【x, n】的数组长度起码应该是k-path.size()才有继续搜索的可能, 那么就有 n-x+1 = k-path.size() , 解方程得 x = n+1 - (k-path.size()), 而且这个x是可以作为起点往下搜的 也就是for(i = s; i<=x; i++) 这里的x是可以取到的