首先,可以搜索DFS的标准解法,不再赘述。
但搜到的dfs一般都不是二叉树这种类型,一般是针对矩阵、字符串的操作。
如果遇到二叉树,如leetcode的113题:求路径总和2.
https://leetcode-cn.com/problems/path-sum-iii/
有人给出的解法是:(这里给出了113和437,他们是类型相似的题目,同一个人给出的解答)
https://leetcode-cn.com/problems/path-sum-ii/solution/113-lu-jing-zong-he-iidi-gui-by-sunny_smile/
class Solution {
public:
vector<vector<int>> res;
vector<int> tmp;
vector<vector<int>> pathSum(TreeNode* root, int sum) {
if(root == nullptr) {
return res;
}
helper(root, sum);
return res;
}
void helper(TreeNode* root, int sum) {
if (root == nullptr) {
return;
}
tmp.push_back(root->val);
if (root->val == sum && root->left == nullptr && root->right == nullptr) {
res.push_back(tmp);
}
if (root->left) {
helper(root->left, sum - root->val);
}
if (root->right) {
helper(root->right, sum - root->val);
}
tmp.pop_back();
}
};
但是这种解法让我困惑的在于:
1.平时的回溯都是 push_back在每一种可能之前,pop在每一种可能之后,为什么这个代码只是所有情况的前后写了一次push和一次pop呢?
这种解法实际上是将各个分支的公共部分提取了出来,那什么时候各个可能的分支会有相同之处呢? 只有处理的是当前状态才会有相同之处,因此这时还可以将sum-root->val提取出来,放在前面,那时,之后各个分支的helper就变成了
sum -= root->val ...(当前状态)
... push (当前状态)
helper(root->left, sum );
helper(root->right, sum );
... pop
经过调试运行,我发现,上面的代码 push和pop的都是这一状态的值,这与dfs理念不同。DFS都是要探究接下来的值是否可行,如果可行的话,就添加,否则就pop。
上面代码相当于:
void helper()
{
do_push (当前状态)
check( 这里不是判断 sum==0, 而是判断当前状态 == sum) {
if ok
add
}
所有可能的结果
do_pop
}
但我更习惯于
void helper() {
check ( 0 == target(类似于这样的边界,如 step == nums.size()或者 tmp.size() == nums.size()) ) {
if ok
add
return; // 这里一般不可以省
}
遍历每一种可能性(有的时候这能写成for循环, 如字符串的下一个位置,矩阵的下一个位置,有的时候不行 , 如遍历四邻域还是直接写四个比较好,遍历二叉树,还是写两个比较好。)
if (root->left) {
tmp.push(下一个可能的状态)
helper(root->left)
tmp.pop();
}
if (root->right) {
tmp.push(下一个可能的状态)
helper(root->left)
tmp.pop();
}
}
所以我写出来下面的代码
void helper(TreeNode* root, int sum) {
if (root == nullptr) {
return;
}
if (0 == sum && root->left == nullptr && root->right == nullptr) {
res.push_back(tmp);
return;
}
if (root->left) {
tmp.push_back(root->left->val);
helper(root->left, sum - root->left->val);
tmp.pop_back();
}
if (root->right) {
tmp.push_back(root->right->val);
helper(root->right, sum - root->right->val);
tmp.pop_back();
}
}