回溯算法概论

回溯:

有递归就会有回溯,递归和回溯相辅相成,回溯通常藏在递归函数的下面。

回溯函数其实就是递归函数,没有单独的回溯函数

效率:

回溯函数是一个纯暴力的搜索。

有的问题用for循环一点一点搜索都搜索不出来,一定要用回溯才能搜索出来

哪些问题for循环一点一点搜索都搜索不出来,一定要用回溯才能搜索出来?

        组合问题。

                e.g. 1234有多少种两两组合?  12 13 14.。。。

        切割问题。

                e.g. 给一个字符串,有几种切割方式?

        子集问题。

                e.g. 1234的子集有哪些?1 2 3 4 12 13 14。。。

        排列问题。

                e.g. 12的排列有12和21.

        棋盘问题。

                e.g. N皇后、解数独

怎么理解回溯法?

把回溯法抽象为图像,做题的时候要画图。

回溯法可以抽象为N叉树,树的宽度是要处理的集合的大小,深度是递归的深度(要通过递归处理)

回溯的模板

在回溯算法中,我的习惯是函数起名字为backtracking,这个起名大家随意。

回溯算法中函数返回值一般为void。

void backtracking(参数){
//什么时候达到了终止条件,树中就可以看出,一般来说搜到叶子节点了,也就找到了满足条件的一条答案,把这个答案存放起来,并结束本层递归。
if (终止条件) {
    存放结果;
    return;
}
//回溯函数遍历过程伪代码如下
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
    处理节点;
    backtracking(路径,选择列表); // 递归,根据树,从上往下递归
    回溯,撤销处理结果
}
}
//为什么要撤销处理结果?
//比如123排列组合问题
//12处理完以后,要把12撤销,组合13;13处理完以后,要把13撤销,组合23

回溯三部曲

递归函数参数返回值

确定终止条件

单层递归逻辑

你可能感兴趣的:(#,7.回溯,算法)