day37回溯算法

1.什么是回溯算法
回溯就是递归问题:
解决组合问题(无顺序),切割问题,子集问题,排列问题(顺序)
所有的回溯可以抽象为一棵树:树 宽度就是for循环大小 树深度就是回溯

void backtracking(参数)
{
  if(终止条件)
  叶子结点收集问题;
  returnfor(集合元素集)//子节点数 
  处理节点;
  递归函数;
  回溯操作;//有撤销的结果
}

2.组合问题
day37回溯算法_第1张图片
回溯三部曲:
递归函数的参数返回值 : void backtracking(n,k,startindex);n个数4(1234),k组合大小,startindex 搜索起始位置 一维数组path(12 13 14 等等)二维数组 res
确定终止条件;path.size() == k ;res,push(path);
单层递归逻辑;、
for(i= startindex;i<=n;i++){
path.push();
backtracking(n.k.i+1);
path.pop();//弹出
剪枝
day37回溯算法_第2张图片
代码:剪枝剪的就是子孩子
for(i = startindex;i<= n-(k-path.size)+1;i++){// 四个子孩子遍历
path.push();
backtracking();//往下搜索过程
path.pop();
}
path.size已经选取的元素大小,还剩k-path.size()个元素要选取;选取的元素至多n-(k-path.size())+1个;
为什么+1,起始位置包括startIndex;
n = 4; k = 3;path.size() = 0;至多从哪里开始: 4-3+1 =2; 234
题目描述
day37回溯算法_第3张图片

分析:
day37回溯算法_第4张图片

int* path;//一维数组,收集单条路径符合的结果
int path_size;
int** ans;// 二维数组 所有结果集
int ans_size;

void backtrack(int k, int n, int sum, int index)// index比如取2之和,从3开始;开始的时候是1 
{
    // 终止条件 沿途取的个数 == k
    if (path_size == k){// 
        if (sum == n){// sum = n 就是目标结果
            int* temp = (int*) malloc((k + 1)* sizeof(int));
            for (int j = 0; j < k; j++){
                temp[j] = path[j];
            }
            ans[ans_size++] = temp;
        }
        return;
    }
    int i;
    // 取数
    for (i = index; i <= 9; i++) {
        sum += i;//取数 + i
        path[path_size++] = i; //路径 push
        backtrack(k, n, sum, ++index);//
        sum -= i;
        path_size--;//pop 回退
    }
}
int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes)
{
    path = (int*)malloc((k + 1) * sizeof(int));
    ans = (int*)malloc(20 * sizeof(int*));
    path_size = 0;
    ans_size = 0;
    backtrack(k, n, 0, 1);
    *returnSize = ans_size;
    *returnColumnSizes = (int*)malloc(sizeof(int)*ans_size);
    for (int i = 0; i < ans_size; i++){
        (*returnColumnSizes)[i] = k;
    }
    return ans;
}

你可能感兴趣的:(算法,数据结构,回溯)