C++牛客网编程(十四)

本文介绍了三个关于二叉树的算法问题:1) 计算节点值和为特定值的路径数量;2) 找到两个节点的最近公共祖先;3) 在二叉搜索树中查找两个节点的最近公共祖先。每个问题都提供了不同的解决方案,包括深度优先搜索(DFS)策略,并强调了处理边界条件和优化时间复杂度的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

二叉树中和为某一值的路径(三)

在二叉树中找到两个结点的最近父结点

二叉搜索树的最近公共父结点


二叉树中和为某一值的路径(三)

描述:给定一个二叉树root和一个整数值 sum ,求该树有多少路径的的节点值之和等于 sum 。

1.该题路径定义不需要从根节点开始,也不需要在叶子节点结束,但是一定是从父亲节点往下到孩子节点

2.总节点数目为n

3.保证最后返回的路径个数在整形范围内(即路径个数小于231-1)

数据范围:0<=n<=10000 −10^9<=节点值<=10^9

思路:通过两个dfs对每个结点进行深度遍历

class Solution {
public:
    int res=0;//数量
    void dfs(TreeNode* root,int sum){
        if(!root) return;
        if(sum==root->val)
            res++;
        dfs(root->left,sum-root->val);
        dfs(root->right,sum-root->val);
    }
    int FindPath(TreeNode* root, int sum) {
        if(!root) return res;
        dfs(root,sum);
        FindPath(root->left,sum);
        FindPath(root->right,sum);
        return res;
    }
};

在二叉树中找到两个结点的最近父结点

描述:给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值 o1 和 o2,请找到 o1 和 o2 的最近公共祖先节点。

数据范围:树上节点数满足 1≤n≤10^5  , 节点值val满足区间 [0,n)

要求:时间复杂度 O(n)

注:本题保证二叉树中每个节点的val值均不相同。

如当输入{3,5,1,6,2,0,8,#,#,7,4},5,1时,二叉树{3,5,1,6,2,0,8,#,#,7,4}如下图所示:

所以节点值为5和节点值为1的节点的最近公共祖先节点的节点值为3,所以对应的输出为3。

节点本身可以视为自己的祖先

思路:查询根结点到所求结点的路径,遍历查询两个路径节点值相同的最后一个结点。

class Solution {
public:
    /**
     * 
     * @param root TreeNode类 
     * @param o1 int整型 
     * @param o2 int整型 
     * @return int整型
     */
    bool find=false;
    void dfs(TreeNode* root,int o,vector<int>& a){
        if(!root) return;
        a.push_back(root->val);
        if(root->val==o){
            find=true;
            return;
        }
        dfs(root->left,o,a);
        dfs(root->right,o,a);
        if(find) return;
        a.pop_back();
    }
    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
        vector<int> a1;
        vector<int> a2;
        int l1,l2,i;
        dfs(root,o1,a1);
        find=false;
        dfs(root,o2,a2);
        l1=a1.size();
        l2=a2.size();
        for(i=0;i<min(l1,l2)&&a1[i]==a2[i];i++);
        i--;
        return a1[i];
    }
};

 重点:在第一次书写该代码时,忽视了深度遍历时何时pop不是路径上的结点的问题。

此外,可以使用递归的方法解决。

思路:如果根结点值和两个结点值相同,则返回根结点;否则,如果两个结点在树上的话,只可能存在三种可能性:都在左子树,都在右子树,或一个在左子树,一个在右子树。

class Solution {
public:
    TreeNode* dfs(TreeNode* root, int o1, int o2) {
        if(root == nullptr) return nullptr; //超过叶节点,返回空
        if(root->val == o1 || root->val == o2) return root; //节点为其中一个
        TreeNode* t1 = dfs(root->left, o1, o2);
        TreeNode* t2 = dfs(root->right, o1, o2);
        if(t1 == nullptr) return t2; //此时两个节点都在右侧
        if(t2 == nullptr) return t1; //此时两个节点都在左侧
        return root; //此时两个节点分别位于左右两侧
    }
    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
        return dfs(root, o1, o2)->val;
    }
};

二叉搜索树的最近公共父结点

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

1.对于该题的最近的公共祖先定义:对于有根树T的两个节点p、q,最近公共祖先LCA(T,p,q)表示一个节点x,满足x是p和q的祖先且x的深度尽可能大。在这里,一个节点也可以是它自己的祖先.

2.二叉搜索树是若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值; 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值

3.所有节点的值都是唯一的。

4.p、q 为不同节点且均存在于给定的二叉搜索树中。

数据范围:

3<=节点总数<=10000

0<=节点值<=10000

思路:借鉴上个问题的递归方法,这个问题增加的是二叉搜索树的条件,即左孩子结点值<根结点值<右孩子节点值。

class Solution {
public:
    TreeNode* dfs(TreeNode* root,int p,int q){
        if(!root) return NULL;
        if(root->val==p||root->val==q) return root;
        int mint=min(p,q),maxt=max(p,q);
        TreeNode* left=dfs(root->left,p,q);
        TreeNode* right=dfs(root->right,p,q);
        if(root->val>maxt) return left;
        if(root->val<mint) return right;
        return root;
    }
    
    int lowestCommonAncestor(TreeNode* root, int p, int q) {
       return dfs(root,p,q)->val;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值