LeetCode(235 & 236):二叉树的最近公共祖先 Lowest Common Ancestor of a Binary Tree(Java)

234 篇文章 1 订阅
177 篇文章 0 订阅

2019.8.1 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)

二叉树的公共祖先是一个经典的问题,在不同约束下有不同的解法:

1.如果该树是二叉搜索树

那么从根节点开始访问,若root值比p和q均小,则根节点移向右子节点;反之若root值比p和q均大,则根节点移向左子节点。第一个遍历到的位于两子树结点值之间的结点即为最近公共祖先。

2.如果该树结点包含指向父节点的指针

问题可以转换为求两个链表的第一个公共结点。如果不包含指向父节点的指针,我们可以通过DFS记录从根节点到p和q的路径,从而转换为求两个路径的第一个公共结点。

3.如果该树是一棵普通的二叉树

可用后序遍历标记法。若pq分别位于左右子树,则当前根节点是最近公共祖先,若pq在同一子树,则深度较小的结点是最近公共祖先。

1.后序遍历二叉树,若子树中访问到p或q,则将p或q返回,否则返回null,从而进行标记。

2.当左右子树均没有访问到p或q时,直接返回null

3.若左子树或右子树仅有一棵包含p或q,则返回该子节点。若左右子树分别包含p和q,则返回当前结点root。由于root的祖先已经无法在不含root的另一子树上访问到p或q,因此函数递归结束仍然返回该结点root。


传送门:二叉搜索树的最近公共祖先

传送门:二叉树的最近公共祖先

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

the definition of LCA: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

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

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

示例 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 为不同节点且均存在于给定的二叉树中。


/**
 * Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
 * the definition of LCA:
 * “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
 * 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
 * 最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
 * 升级版:给定的是二叉树而非搜索树
 */

public class LowestCommonAncestor0fABinarySearchTree {
    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            val = x;
        }
    }

    //求二叉搜索树的最近公共祖先
    //从根节点开始访问,若root值比p和q均小,则根节点移向右子节点;反之若root值比p和q均大,则根节点移向左子节点
    //第一个遍历到的位于两子树结点值之间的结点即为最近公共祖先
    public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
        while(root != null){
            if(root.val < p.val && root.val < q.val)
                root = root.right;
            else if(root.val > p.val && root.val > q.val)
                root = root.left;
            else
                break;
        }
        return root;
    }

    //升级版:求二叉树的最近公共祖先
    //若二叉树结点有指向父结点的指针,或创立数组建立root到pq的路径,问题可以转换为求两个链表的第一个公共结点
    //若二叉树结点没有指向父节点的指针,可用后序遍历标记法。
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //后序遍历二叉树,若子树中访问到p或q,则将p或q返回,否则返回null,从而进行标记
        if(root == null || root == p || root == q)
            return root;

        //当左右子树均没有访问到p或q时,直接返回null
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if(left == null && right == null)
            return null;

        //若左子树或右子树仅有一棵包含p或q,则返回该子节点。
        //若左右子树分别包含p和q,则返回当前结点root。
        //由于root的祖先已经无法在不含root的另一子树上访问到p或q,因此函数递归结束仍然返回该结点root
        return left != null && right != null ? root : (left != null ? left : right);
    }

}



#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值