回溯算法理论基础
1、回溯算法基础
1. 在二叉树系列中,我们已经不止一次,提到了回溯,例如二叉树:以为使用了递归,其实还隐藏着回溯
if (node->left) { // 左
depth++; // 深度+1
getdepth(node->left, depth);
depth--; // 回溯,深度-1
}
if (node->right) { // 右
depth++; // 深度+1
getdepth(node->right, depth);
depth--; // 回溯,深度-1
}
return ;
在求最大深入时,我们在退出一层递归时,需要将depth ——来减去本次遍历。
2. 在求路径总和时,我们遍历一层时,会将count进行–之后结束遍历后,我们会将count进行++回溯
if (cur->left) { // 左
count -= cur->left->val; // 递归,处理节点;
if (traversal(cur->left, count)) return true;
count += cur->left->val; // 回溯,撤销处理结果
}
if (cur->right) { // 右
count -= cur->right->val;
if (traversal(cur->right, count)) return true;
count += cur->right->val;
}
return false;
2、回溯三部曲
1.确定参数和返回条件
void backtracking(参数);//一般来说回溯参数会返回一个数组,数组中的元素是满足要求的组合集合
<T> result;//用于存取结果的数组
<T> path;//用于存取单层符合要求的数组
2.确定结束条件和处理逻辑
if(终止条件){//一般是path中的数据满足了某个要求
将数据放入result中;
return;
}
3.确定单层递归逻辑
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
3、以一棵树来进行演示
在单层遍历的逻辑当中,有两个关键的逻辑:
1.for循环
可以认为for循环所遍历的,是纵向的集合数量,如第一层中满足条件的集合的size有四个,那么就需要使用for循环将四种可能的结果全部遍历出来,但是想要得知下一步的具体数据,就需要进行递归遍历了
2.backtracking递归
通过backtracking,我们才知道了单个集合中的具体数据,以及该数据是否满足结束条件的要求,并且通过不断的递归,我们才能不断扩充path数组,得到一条具体的路径值。在backtracking之后,一定要回溯 将本次的数据从path中删除。
4、回溯遍历较为抽象,需要具体实例才能完全掌握!!!