二叉搜索树和二叉树的公共祖先

85 阅读1分钟

二叉搜索树

题目

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

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

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

image.png

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

利用二叉树的特点 其左节点小于根结点小于右节点。利用其有序的特性,进行如下两种方法

  1. 按照从root出发,查找目标节点的路径,最后返回两路径的最近重复值。
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        List<TreeNode> path_p = get_path(root,p);
        List<TreeNode> path_q = get_path(root,q);
        TreeNode ans = null;
        for(int i=0;i<path_p.size() && i< path_q.size();i++){
            if(path_p.get(i) == path_q.get(i)){
                ans = path_q.get(i);
            }else{
                break;
            }
        }
        return ans;
    }
    public List<TreeNode> get_path(TreeNode root,TreeNode target){
        List<TreeNode> path = new LinkedList<>();
        TreeNode node = root;
        while(node != null){
            if(node.val != target.val){
                path.add(node);
            }
            if(node.val > target.val){
                node = node.left;
            }else if(node.val < target.val){
                node = node.right;
            }else{
                break;
            }
        }
        path.add(node);
        return path;
    }
}

2.按照二叉搜索树的特性,其祖节点 大于等于左边节点,小于等于右边节点的特性。

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

二叉树

由于二叉树是无序的,所以不能利用二叉搜索树的性质去解。

方法1:利用map保存节点和其父节点。利用set判断其是否公共父节点,分别从目标值开始向父节点遍历。

class Solution {

    Map<Integer,TreeNode> map;
    Set<Integer> set;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        map = new HashMap<>();
        set = new HashSet<>();
        dfs(root);

        while(p != null){
            set.add(p.val);
            p = map.get(p.val);
        }

        while(q != null){
            if(set.contains(q.val)){
                return q;
            }
            q = map.get(q.val);
        }
        return null;
        
    }

    public void dfs(TreeNode root){
        if (root.left!=null){
            map.put(root.left.val,root);
            dfs(root.left);
        }
        if(root.right != null){
            map.put(root.right.val,root);
            dfs(root.right);
        }

    }
}

方法2:利用回溯

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

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

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