总结所有有关二叉树公共祖先问题

Posted 满眼*星辰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了总结所有有关二叉树公共祖先问题相关的知识,希望对你有一定的参考价值。

满二叉树最近公共祖先

将一棵无穷大满二叉树的结点按根结点一层一层地从左往右编号,根结点编号为1。现给定a,b为两个结点。设计一个算法,返回a、b最近的公共祖先的编号。注意其祖先也可能是结点本身。
测试样例:
2,3
返回:1

链接:https://www.nowcoder.com/questionTerminal/70e00e490b454006976c1fdf47f155d9
来源:牛客网

思路

因为是按照0,1,2,3这样的满二叉树,所以可以直接用公式找到其父亲节点
父亲节点 = 孩子节点 / 2

找到最低层的那个节点,然后向上找两个节点的父节点,判断两者父亲节点是否相同

代码

import java.util.*;
public class LCA {
    public int getLCA(int a, int b) {
        if(a > b) {
            int tmp = a;
            a = b;
            b = tmp;
        }
        if(a == b) return a;
//b最大了
        while(a != b) {
            b = b/2;
            if(b < a) {
                a = a/2;
                if(a == b) break;
            }
        }
        return a;
    }
}

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

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

百度百科中最近公共祖先的定义为:“对于有根树 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, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

所有节点的值都是唯一的。 p、q 为不同节点且均存在于给定的二叉搜索树中。

在这里插入图片描述

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof

思路

若 root.val < p.val,则 p 在 root 右子树 中;
若 root.val > p.val,则 p 在 root 左子树 中;
若 root.val = p.val ,则 p 和 root 指向 同一节点 。

代码-遍历

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while(true) {
            if(root.val > p.val && root.val > q.val) {
                root = root.left;
            }else if(root.val < p.val && root.val < q.val) {
                root = root.right;
            }else break;
        }
        return root;
    }
}

代码-递归

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root.val < p.val && root.val < q.val)
            return lowestCommonAncestor(root.right, p, q);
        if(root.val > p.val && root.val > q.val)
            return lowestCommonAncestor(root.left, p, q);
        return root;
    }
}

二叉树的最近公共祖先

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

百度百科中最近公共祖先的定义为:“对于有根树 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。因为根据定义最近公共祖先节点可以为节点本身。

说明:

所有节点的值都是唯一的。 p、q 为不同节点且均存在于给定的二叉树中。

在这里插入图片描述

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof

思路

  1. 根节点本身是否是p或者q当中的某个节点
  2. 递归根的左和根的右
    2.1 左右两边都不为空:root是公共祖先
    2.2 左边不为空,右边为空:左边第一次找到的节点就是公共祖先
    2.3 左边为空,右边不为空:右边第一个节点就是公共祖先
  3. 如果都没有,则返回null

代码-递归

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        if(root == q || root == p) return root;

        TreeNode left = lowestCommonAncestor(root.left,p,q);
        TreeNode right = lowestCommonAncestor(root.right,p,q);

        if(left != null && right != null) return root;

        if(left != null) return left;

        if(right != null) return right;

        return null;
    }
}

以上是关于总结所有有关二叉树公共祖先问题的主要内容,如果未能解决你的问题,请参考以下文章

二叉树:公共祖先问题

二叉树有关习题整理145二叉树的后序遍历 94二叉树的中序遍历 572另一棵树的子树 236二叉树的最近公共祖先 JZ36二叉搜索树与双向链表 - 牛客

leetcode 236. 二叉树的最近公共祖先

236. 二叉树的最近公共祖先

236. 二叉树的最近公共祖先[中等]

编程算法 - 二叉树的最低公共祖先 代码(C)