【递归、搜索与回溯】二叉树的深搜

这篇博客记录了关于二叉树深搜的几道题目,包括求根节点到叶节点数字之和、二叉树剪枝、验证二叉搜索树、二叉树的所有路径。

cpp 复制代码
class Solution {
public:
    int sumNumbers(TreeNode* root) 
    {
        return dfs(root,0);
    }
    int dfs(TreeNode* root, int presum)
    {
        presum = presum*10 + root->val;
        if(!root->left && !root->right) return presum;
        int left = 0, right = 0;
        if(root->left) left = dfs(root->left, cursum);
        if(root->right) right = dfs(root->right, cursum);
        return left + right;
    }
};

题目分析:如下图所示,假设我们递归到5时,只需关注要干什么事情才能达到目的,此时需要拿到1258、12594、125931,然后向上返回它们之和。在递归到5时,需要接收传入之前路径的数字即12,以便计算最终结果。当拿到12后,需要加上当前节点值即125,传给左边得到1258,左边返回来1258,;传给右边得到1259,返回来12594+125931。然后把左边和右边返回值之和返回给上面。

因此,我们可以得到递归函数:

1.函数头:int dfs(root, presum),其返回值是以当前根结点所有相连之和。

2.函数体:执行1234。

3.递归出口:遇到叶子节点。并且是在第1步之后执行递归出口,因为需要把叶子节点的值加上。

cpp 复制代码
class Solution {
public:
    TreeNode* pruneTree(TreeNode* root) 
    {
        if(root == nullptr) return nullptr;

        root->left = pruneTree(root->left);
        root->right = pruneTree(root->right);
        if(root->left == nullptr && root->right == nullptr && root->val == 0) 
        {
            //delete root;
            root = nullptr;
        }
        return root;
    }
};

题目分析 :这道题的子问题是给一棵树的头指针,返回删除后的指针。给一个节点,只有知道左子树的信息和右子树的信息之后,才能决定当前节点要不要被剪掉,因此是一个后序遍历

1.函数头:Node* dfs(root)

2.函数体:

1)处理左子树

2)处理右子树

3)判断左子树和右子树是不是空,并且本身是不是空

3.递归出口:root==nullptr,返回nullptr

cpp 复制代码
class Solution 
{
    long long prev = LONG_MIN;
public:
    bool isValidBST(TreeNode* root) 
    {
        if(root == nullptr) return true;
        bool left = isValidBST(root->left);
        //剪枝
        if(left == false) return false;
        bool cur = false;
        if(root->val > prev) cur = true;
        //剪枝
        if(cur == false) return false;
        prev = root->val;
        bool right = isValidBST(root->right);
        return left && cur && right;  
    }
};

题目分析:我们用到二叉搜索树的中序遍历结果是一个有序的序列。为此,我们可以搞一个前驱的全局变量prev,初始化为LONG_MIN(由于这道题给的数据范围,不能初始化为INT_MIN),这个全局变量的意思就是在遍历到某一个位置后,这个位置的前驱是多少,只需要判断当前位置的值和prev大小,只有当前位置的值大于prev时才符合要求。

为了解决这道题,我们有两个策略:

1.左子树是二叉搜索树,当前节点也是二叉搜索树,右子树也是二叉搜索树。

2.剪枝。在1的基础上,如果某个左子树不符合要求,就可以直接返回false,无需判断上一节点和其右子树。同理,如果当前节点不符合要求,直接返回false,无需判断其右子树。

cpp 复制代码
class Solution 
{
    vector<string> ret;
    string path;
public:
    vector<string> binaryTreePaths(TreeNode* root) 
    {
        dfs(root,path);
        return ret;
    }
    void dfs(TreeNode* root, string path)
    {
        if(root == nullptr) return;
        if(root->left == nullptr && root->right == nullptr)
        {
            path += to_string(root->val);
            ret.push_back(path);
            return;
        }
        else
        {
            path += to_string(root->val);
            path += "->";
            dfs(root->left, path);
            dfs(root->right, path);
        }
    }
};

题目分析:这道题需要创建一个全局变量ret,另外需要将path作为参数传入dfs,这样在回溯时就不需要"恢复现场"。

函数头:void dfs(root, path)

函数体:if(root == 叶子节点)不需要加->;

if(root != 叶子节点)需要加->;

相关推荐
呆瑜nuage4 分钟前
数据结构——堆
数据结构
蓝澈112110 分钟前
弗洛伊德(Floyd)算法-各个顶点之间的最短路径问题
java·数据结构·动态规划
zl_dfq13 分钟前
数据结构 之 【堆】(堆的概念及结构、大根堆的实现、向上调整法、向下调整法)(C语言实现)
数据结构
127_127_12716 分钟前
2025 FJCPC 复建 VP
数据结构·图论·模拟·ad-hoc·分治·转化
闪电麦坤9519 分钟前
数据结构:二维数组(2D Arrays)
数据结构·算法
一定要AK3 小时前
萌新赛练习
数据结构
随缘而动,随遇而安10 小时前
第八十八篇 大数据中的递归算法:从俄罗斯套娃到分布式计算的奇妙之旅
大数据·数据结构·算法
水木兰亭14 小时前
数据结构之——树及树的存储
数据结构·c++·学习·算法
Jess0715 小时前
插入排序的简单介绍
数据结构·算法·排序算法
老一岁15 小时前
选择排序算法详解
数据结构·算法·排序算法