二叉搜索树中两个节点的最近公共祖先节点

标题读起来稍微有点小绕,这是我在力扣上今天碰到的一道题,需要用程序找出二叉搜索树中两个指定节点的最近公共祖先节点。

最近可以理解为从上往下看最早出现,公共祖先节点就不用多说了,详细题目如下:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

开始刚一读题也是有点迷,主要原因是不知道什么是二叉搜索树,查了一下,发现在二叉搜索树中,每一个节点的左子树上的节点全部小于它本身节点,右子树上节点正好相反。

第一直觉是既然给出的是二叉搜索树,那解法应该可以利用它的特性,由于是树状结构,果断想到了递归。

从根节点开始递归,如果它大于两个节点,或小于两个节点,那就说明,两个节点位于它的同一个子树上,这种情况下,由于是二叉树,它本身肯定不是最近祖先节点(二叉树最多只有两个子节点,如果两节点位于同一子树,那么至少是在当前节点的下下层,这样看来,当前节点的其中一个子节点会更近)。

如果根节点大于其中一个节点而且小于另一个节点,就说明一个节点位于根节点的左子树,另一个位于右子树。

那么它是不是最近祖先节点呢?假设它不是,首先由于是二叉树结构,位于树中的两个节点必然有一个最近祖先节点。如果它不是那么必然在它之下,就说明在根节点的左子树或右子树上存在一个两节点的祖先节点,这样的话,两节点必须位于根节点的同一子树上,那就和之前的已有条件冲突了,所以说明这是不可能发生的情况,反向推理,我们已经证明了这种情况下根节点不会不是两节点的最近祖先节点,那么它就必然是两节点的最近祖先节点。

还有一种特殊情况,两节点的最近祖先节点是两节点其中之一,那么两节点必然位于的层级不同,通过递归寻找节点的途中,必然会先找到他们的最近祖先节点(位于较高层级的那个)。

最终代码如下(其实还可以优化,当前节点大于两节点或小于两节点的时候,只需要递归它的一个子树即可):

 

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    TreeNode node = null;

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        findCommonNode(root, p, q);
        return node;
    }

    public void findCommonNode(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null)
            return;
        if (root.val == p.val || root.val == q.val) {
            node = root;
            return;
        }
        if ((root.val > p.val && root.val < q.val) || (root.val < p.val && root.val > q.val)) {
            node = root;
            return;
        }
        findCommonNode(root.left, p, q);
        findCommonNode(root.right, p, q);
    }
}

 

posted @ 2020-11-28 11:11  无心大魔王  阅读(522)  评论(0编辑  收藏  举报