• 二叉树的最近公共祖先、二叉搜索数的最近公共祖先


    目录

    二叉树的最近公共祖先

    二叉搜索数的最近公共祖先

    二叉树的最近公共祖先Ⅱ

    二叉树的最近公共祖先Ⅲ

    二叉树的最近公共祖先Ⅳ


    二叉树的最近公共祖先

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

    百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

    例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4]

    示例 1:

    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
    输出: 3
    解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
    示例 2:

    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
    输出: 5
    解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。

    核心:后序遍历,是二叉树中回溯的体现! 

    1. class Solution {
    2. public:
    3. TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    4. if(root==p || root==q ||root==nullptr)return root;
    5. TreeNode* left=lowestCommonAncestor(root->left,p,q);
    6. TreeNode* right=lowestCommonAncestor(root->right,p,q);
    7. if(left && right){
    8. return root;
    9. }else if(left==nullptr && right!=nullptr){
    10. return right;
    11. }else if(left!=nullptr && right==nullptr){
    12. return left;
    13. }else{
    14. return nullptr;
    15. }
    16. }
    17. };

    二叉搜索数的最近公共祖先

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

    百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

    例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5]

    示例 1:

    输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
    输出: 6 
    解释: 节点 2 和节点 8 的最近公共祖先是 6。
    示例 2:

    输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
    输出: 2
    解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

    利用BST的特性,左子树结点比根节点小,右子树结点比根节点大 

    1. class Solution {
    2. public:
    3. TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    4. if((root->val-p->val) * (root->val-q->val) <=0){
    5. return root;
    6. }
    7. return lowestCommonAncestor(p->valval?root->left:root->right,p,q);
    8. }
    9. };

    二叉树的最近公共祖先Ⅱ

    给定一棵二叉树的根节点 root,返回给定节点 p 和 q 的最近公共祖先(LCA)节点。如果 p 或 q 之一 不存在 于该二叉树中,返回 null。树中的每个节点值都是互不相同的。

    根据维基百科中对最近公共祖先节点的定义:“两个节点 p 和 q 在二叉树 T 中的最近公共祖先节点是 后代节点 中既包括 p 又包括 q 的最深节点(我们允许 一个节点为自身的一个后代节点 )”。一个节点 x 的 后代节点 是节点 x 到某一叶节点间的路径中的节点 y。

    示例 1:

    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
    输出: 3
    解释: 节点 5 和 1 的共同祖先节点是 3。


    示例 2:

    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
    输出: 5
    解释: 节点 5 和 4 的共同祖先节点是 5。根据共同祖先节点的定义,一个节点可以是自身的后代节点。


    示例 3:

    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 10
    输出: null
    解释: 节点 10 不存在于树中,所以返回 null。

     此题与基础的二叉树最近公共祖先的区别在于,如果p或q结点并不存在于树中,则要返回nullptr

    1. class Solution {
    2. public:
    3. bool findp=false;
    4. bool findq=false;
    5. TreeNode* dfs(TreeNode* root, TreeNode* p, TreeNode* q){
    6. if(root==nullptr)return root;
    7. TreeNode* left=dfs(root->left,p,q);
    8. TreeNode* right=dfs(root->right,p,q);
    9. if(left && right){
    10. return root;
    11. }
    12. if(root->val==p->val){
    13. findp=true;
    14. return root;
    15. }
    16. if(root->val==q->val){
    17. findq=true;
    18. return root;
    19. }
    20. return left==nullptr?right:left;
    21. }
    22. TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    23. TreeNode* ans=dfs(root,p,q);
    24. if(!findp || !findq){
    25. return nullptr;
    26. }
    27. return ans;
    28. }
    29. };

    二叉树的最近公共祖先Ⅲ

    给定一棵二叉树中的两个节点 p 和 q,返回它们的最近公共祖先节点(LCA)。

    每个节点都包含其父节点的引用(指针)。Node 的定义如下:

    class Node {
        public int val;
        public Node left;
        public Node right;
        public Node parent;
    }
    根据维基百科中对最近公共祖先节点的定义:“两个节点 p 和 q 在二叉树 T 中的最近公共祖先节点是后代节点中既包括 p 又包括 q 的最深节点(我们允许一个节点为自身的一个后代节点)”。一个节点 x 的后代节点是节点 x 到某一叶节点间的路径中的节点 y。

    示例 1:


    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
    输出: 3
    解释: 节点 5 和 1 的最近公共祖先是 3。
    示例 2:


    输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
    输出: 5
    解释: 节点 5 和 4 的最近公共祖先是 5,根据定义,一个节点可以是自身的最近公共祖先。
    示例 3:

    输入: root = [1,2], p = 1, q = 2
    输出: 1

    此题特点在于,没有直接给根节点,而是给了两个子节点的父指针,所以很简单,直接找到根节点,将问题转化为①即可。

    1. /*
    2. // Definition for a Node.
    3. class Node {
    4. public:
    5. int val;
    6. Node* left;
    7. Node* right;
    8. Node* parent;
    9. };
    10. */
    11. class Solution {
    12. public:
    13. Node* dfs(Node* root,Node* p,Node* q){
    14. if(root==nullptr || root==p || root==q){
    15. return root;
    16. }
    17. Node* left=dfs(root->left,p,q);
    18. Node* right=dfs(root->right,p,q);
    19. if(left && right){
    20. return root;
    21. }
    22. return left==nullptr?right:left;
    23. }
    24. Node* lowestCommonAncestor(Node* p, Node * q) {
    25. Node* root=p;
    26. while(root->parent!=nullptr){
    27. root=root->parent;
    28. }
    29. root=dfs(root,p,q);
    30. return root;
    31. }
    32. };

    二叉树的最近公共祖先Ⅳ

    给定一棵二叉树的根节点 root 和 TreeNode 类对象的数组(列表) nodes,返回 nodes 中所有节点的最近公共祖先(LCA)。数组(列表)中所有节点都存在于该二叉树中,且二叉树中所有节点的值都是互不相同的。

    我们扩展二叉树的最近公共祖先节点在维基百科上的定义:“对于任意合理的 i 值, n 个节点 p1 、 p2、...、 pn 在二叉树 T 中的最近公共祖先节点是后代中包含所有节点 pi 的最深节点(我们允许一个节点是其自身的后代)”。一个节点 x 的后代节点是节点 x 到某一叶节点间的路径中的节点 y。

    示例 1:


    输入: root = [3,5,1,6,2,0,8,null,null,7,4], nodes = [4,7]
    输出: 2
    解释: 节点 4 和 7 的最近公共祖先是 2。
    示例 2:


    输入: root = [3,5,1,6,2,0,8,null,null,7,4], nodes = [1]
    输出: 1
    解释: 单个节点的最近公共祖先是该节点本身。

    示例 3:


    输入: root = [3,5,1,6,2,0,8,null,null,7,4], nodes = [7,6,2,4]
    输出: 5
    解释: 节点 7、6、2 和 4 的最近公共祖先节点是 5。
    示例 4:


    输入: root = [3,5,1,6,2,0,8,null,null,7,4], nodes = [0,1,2,3,4,5,6,7,8]
    输出: 3
    解释: 树中所有节点的最近公共祖先是根节点。

    不同的是,这次不再是只寻找两个孩子的父亲结点,而是寻找一堆孩子的父亲节点,因此唯一的区别就是在递归终止条件中要对所有孩子结点进行for遍历一次,只要当前根节点与其中一个孩子结点相同,则返回root。最后(也就是最顶层)的root,它的孩子一定包含了所有的孩子节点。

    1. /**
    2. * Definition for a binary tree node.
    3. * struct TreeNode {
    4. * int val;
    5. * TreeNode *left;
    6. * TreeNode *right;
    7. * TreeNode() : val(0), left(nullptr), right(nullptr) {}
    8. * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    9. * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
    10. * };
    11. */
    12. class Solution {
    13. public:
    14. TreeNode* lowestCommonAncestor(TreeNode* root, vector &nodes) {
    15. for(auto &node:nodes){
    16. if(root==node || root==nullptr){
    17. return root;
    18. }
    19. }
    20. TreeNode* left=lowestCommonAncestor(root->left,nodes);
    21. TreeNode* right=lowestCommonAncestor(root->right,nodes);
    22. if(left && right)return root;
    23. return left!=nullptr?left:right;
    24. }
    25. };

  • 相关阅读:
    基于JavaSwing开发汉诺塔游戏 将盘子从A塔搬运B塔和C塔(自动演示 重新开始) 课程设计 大作业
    jenkins pipeline 通过withCredentials连接项目服务器进行自动部署
    软件过程与管理_期末复习知识点回顾总结
    C++初阶(stack+queue)
    js-算术三元组的数目
    2022最全Java后端面试真题、两万字1000+道堪称史上最强的面试题不接受任何反驳
    关于CSS 盒子模型的基础教程
    【Kubernetes】初识k8s--扫盲阶段
    权限模型 DAC ACL RBAC ABAC
    母婴服务预约小程序的效果如何
  • 原文地址:https://blog.csdn.net/Jason6620/article/details/126471347