目录
回溯算法
回溯算法是一种纯暴力搜索。所有的回溯法都可以抽象为一个树形结构。
回溯算法解决问题
- 组合问题(不强调元素顺序)
- 切割问题
- 子集问题
- 排列问题(强调元素顺序)
- 棋盘问题(N皇后、解数独)
回溯法模板
一般回溯函数的返回值为空,函数名设为backtracking。
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
回溯三部曲
- 确定递归函数的参数和返回值
- 确定终止条件
- 确定单层搜索(递归)的逻辑
77.组合
题目链接:力扣
题目描述:给定两个整数 n
和 k
,返回范围 [1, n]
中所有可能的 k
个数的组合。
重点在于分析清楚中间的过程再套模板!
动态申请的一维数组在存放到结果集的时候要创建临时变量,不能直接将一维数组存放在到结果集,因为其地址会随着回溯不断变化。
int* path; //存放每个可能
int path_num;
int** ret; //存放返回结果
int ret_num;
void backtracking(int n,int k,int startIndex){
//终止条件
if(path_num==k){
//path是动态申请的,如果直接放入二维数组,地址会随回溯而变化
int *temp=(int*)malloc(sizeof(int)*k);
for(int i=0;i<k;i++){
temp[i]=path[i];
}
ret[ret_num++]=temp;
return ;
}
//处理单层搜索
for(int i=startIndex;i<=n;i++){
path[path_num++]=i;
//递归
backtracking(n,k,i+1);
//回溯
path_num--;
}
}
int** combine(int n, int k, int* returnSize, int** returnColumnSizes){
path=(int*)malloc(sizeof(int)*k);
//结果集要足够大,1000就不行
ret=(int**)malloc(sizeof(int*)*10000);
path_num=ret_num=0;
backtracking(n,k,1);
*returnSize=ret_num;
*returnColumnSizes=malloc(sizeof(int)*(ret_num));
for(int i=0;i<ret_num;i++){
(*returnColumnSizes)[i]=k;
}
return ret;
}