236. Lowest Common Ancestor of a Binary Tree

一、题目

  1、审题

  

  2、分析

    求二叉树中 p、q 节点的最小共同祖先节点。

 

二、解答

  1、思路

    方法一、

      采用循环查找。

      ①、若 root 为 p 或者 q ,则返回 root

      ②、若 p、q 分布在 root 不同的左右子树,则返回 root

      ③、若 p、q 均为 root 左子树,则 root = root.left; 若 p、q均在右子树,则 root = root.right。

 1     public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
 2         while(root != null) {
 3             if(root.val == p.val || root.val == q.val)
 4                 return root;
 5             
 6             boolean pInLeft = isChildren(root.left, p);
 7             boolean qInRight = isChildren(root.right, q);
 8 
 9             if((pInLeft && qInRight) || (!pInLeft && !qInRight))
10                 return root;
11             
12             if(pInLeft)    // p、q 均在 left
13                 root = root.left;
14             else     // p、q 均在 right
15                 root = root.right;
16         }
17         return null;
18     }
19     
20     private boolean isChildren(TreeNode root, TreeNode p) {
21         TreeNode node = root;
22         while(node != null) {
23             if(node.val == p.val)
24                 return true;
25             else 
26                 return isChildren(root.left, p) || isChildren(root.right, p);
27         }
28         return false;
29     }

 

  方法二、

    采用递归查找。

    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)
            return right;
        if(right == null)
            return left;
        // 分别在左右子树
        return root;
    }

 

  方法三、

    采用 Map 存储每个节点和该节点的父节点。

    最终采用 Set 存储 p 的所有祖先节点,q依次向祖先节点移动,找出第一次出现在 Set 中的节点即为 p、q 最小祖先节点。

 1   public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
 2         HashMap<TreeNode, TreeNode> parent = new HashMap<>();
 3         Deque<TreeNode> stack = new ArrayDeque<TreeNode>();
 4         parent.put(root, null);
 5         stack.push(root);
 6         
 7         // paretn 同时包含 p、q 则跳出循环 
 8         while(!parent.containsKey(p) || !parent.containsKey(q)) {
 9             TreeNode node = stack.pop();
10             if(node.left != null) {
11                 parent.put(node.left, node);
12                 stack.push(node.left);
13             }
14             
15             if(node.right != null) {
16                 parent.put(node.right, node);
17                 stack.push(node.right);
18             }
19         }
20         
21         Set<TreeNode> ancestors = new HashSet<>();
22         while(p != null) {
23             ancestors.add(p);
24             p = parent.get(p);
25         }
26         while(!ancestors.contains(q)) 
27             q = parent.get(q);
28         return q;
29     }

 

转载于:https://www.cnblogs.com/skillking/p/9939337.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值