剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

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

百度百科中最近公共祖先的定义为:“对于有根树 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 为不同节点且均存在于给定的二叉搜索树中。

解题思路:

法1:两次寻找。寻找节点p并沿途将经过的节点存入队列,寻找节点q并沿途将经过的节点存入另一个队列。在队列都不为空的情况下,两个队列同时出队直到出队元素不同,则上一次出队的元素即为公共祖先。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    boolean flagp = false;
    boolean flagq = false;
    Queue<TreeNode> queuep = new LinkedList<TreeNode>();
    Queue<TreeNode> queueq = new LinkedList<TreeNode>();
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        TreeNode ret = new TreeNode();;
        searchp(root, p);
        searchq(root, q);
        while(!queueq.isEmpty() && !queuep.isEmpty() && queuep.peek().val == queueq.peek().val){
            ret = queuep.poll();
            queueq.poll();
        }
        return ret;
    }
    public void searchp(TreeNode root, TreeNode p){
        if(flagp == true) return;
        if(flagp == false && p.val > root.val){
            queuep.offer(root);
            searchp(root.right, p);
        }
        else if(flagp == false && p.val < root.val){
            queuep.offer(root);
            searchp(root.left, p);
        }
        else if(flagp == false && p.val == root.val){
            queuep.offer(root);
            return;
        }
    }
    public void searchq(TreeNode root, TreeNode q){
        if(flagq == true) return;
        if(flagq == false && q.val > root.val){
            queueq.offer(root);
            searchq(root.right ,q);
        }
        else if(flagq == false && q.val < root.val){
            queueq.offer(root);
            searchq(root.left ,q);
        }
        else if(flagq == false && q.val == root.val){
            queueq.offer(root);
            return;
        }
    }

两个查找方法目的是存入两个队列,也可以新建两个队列,将其作为形参传入查找方法。

时间复杂度是O(n),空间复杂度是O(n)。n是二叉树节点数。

法2:一次查找法。利用二叉树存储的特点,p和q的共同祖先的val必然满足要求:

p.val >= root.val && q.val <= root.val || p.val <= root.val && q.val >= root.val

而另外两种情况分别是p、q在当前节点的左侧或右侧,需要继续向下寻找。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while(true){
            if(p.val >= root.val && q.val <= root.val || p.val <= root.val && q.val >= root.val)
                return root;
            if(p.val > root.val && q.val > root.val)
                root = root.right;
            if(p.val < root.val && q.val < root.val)
                root = root.left;
        }
    }
}

时间复杂度:O(n),空间复杂度:O(1)。n是二叉树节点数。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值