回溯算法基础知识

1、回溯法也可以叫做回溯搜索法,它是一种搜索的方式
2、回溯是递归的副产品,有递归就会有回溯
3、回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案。如果想要回溯高效一点,可以加入剪枝的操作
4、回溯法解决的问题:
(1) 组合问题:N个数里面按一定规则找出k个数的集合
注: 一个集合求组合的话,就需要startIndex。例如:组合和组合Ⅲ;
如果是多个集合求组合的话,各个集合之间相互不影响,那么就不用startIndex。例如:电话号码的字母组合。
(2) 切割问题:一个字符串按一定规则有几种切割方式
(3) 子集问题:一个N个数的集合里有多少符合条件的子集
(4) 排列问题:N个数按一定规则全排列,有几种排列方式
注意:去重问题必须得先排序,然后建议使用used数组的方式进行去重
(5) 棋盘问题:N皇后,解数独等等
注:组合是不强调元素顺序的,排列是强调元素的顺序
例如:{1, 2}, {2, 1}在组合上,就是一个集合;而在排列上,就是两个集合
5、如何理解回溯:
回溯法解决的问题都可以抽象为树形结构。因为回溯法解决的都是在集合中递归查找子集,集合的大小构成了树的宽度,递归的深度构成了树的深度。
递归要有终止条件,所以必然是一颗高度有限的树(N叉树)
回溯法模板:
1、回溯函数模板的参数和返回值
回溯算法中函数的返回值一般是void。回溯算法需要的参数不容易一次就确定下来,所以一般是先写逻辑,然后需要什么参数,就填什么参数。
回溯函数伪代码:

void backtracking(参数)

2、回溯函数终止条件
什么时候达到终止条件,树中就可以看出,一般来说搜到叶子结点了,也就找到了满足条件的一条答案,把这个答案存起来,并结束本层递归。

if(终止条件){
     
    存放结果;
    return;
}

3、回溯搜索的遍历过程

for(选择 : 本层集合中元素(树中结点孩子的数量就是集合的大小)){
     
    处理结点;
    backtracking(路径, 选择列表);//递归
    回溯,撤销处理结果
}

for循环就是遍历集合区间,可以理解一个结点有多少个孩子,这个for循环就执行多少次;backtracking这里自己调用自己,实现递归
for循环可以理解是横向遍历,backtracking(递归)就是纵向遍历,这样就把这棵树全部遍历完了,一般来说,搜索叶子结点就是找的其中一个结果了。
回溯算法模板框架:

void backtracking(参数){
     
    if(终止条件){
     
        存放结果;
        return;
    }
    for(选择 : 本层集合中元素(树中结点孩子的数量就是集合的大小)){
     
        处理结点;
        backtracking(路径, 选择列表);//递归
        回溯,撤销处理结果
    }
}

你可能感兴趣的:(算法,java)