回溯思想简单来说:从一条路往前走,能进则进,不能进则退回来,换一条路再试。当然这样也太抽象了,运用在算法里面的思想就是转化为树和图。回溯法思路的简单描述是:把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。
和动态规划一样,也有一个三板斧:
1.dfs函数参数的确定
2.确定递归终止条件
3.确定单层搜索逻辑
回溯算法适合:由多个步骤组成的问题,并且每个步骤都有多个选择项,所有就是类似一个树形结构。
如果总结一下的话,回溯还有一个模板,用伪代码实现一下:
function dfs(参数列表){
if(终止条件){
存放结果
return
}
for(选择:本层集合中的元素){
处理节点
dfs(参数列表(路径))
回溯,撤销处理结果
}
}
接下来用几道经点题来按照这三部曲实现一下:
1.二叉树中和为某一值的路径
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
三板斧分析:首先定义一个结果数组results来接收所有路径。dfs函数的参数接受根节点root以及一个路径path(一般用字符串表示)。再来看dfs的终止条件,很显然到达叶子节点就可以停止遍历,并且将其推入results中。接下来就是单层搜索逻辑的确定,一二步的确定也是在为第三步做一个铺垫,当root不为空时,path就进行字符串拼接,再判断是否是叶子节点,不是的话进行dfs深度优先左右节点。并将新的path传下去。上代码:
var pathSum = function(root, target) {
let result