【Leetcode】236. Lowest Common Ancestor of a Binary Tree

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

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

        _______3______
       /              \
    ___5__          ___1__
   /      \        /      \
   6      _2       0       8
         /  \
         7   4

For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

Tips:求一颗普通二叉树中两个结点的最低公共子节点。

解法一:分别求出从根节点到两个子节点的路径,在根据两个路径找到两个结点的最后一个公共结点。

package medium;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import dataStructure.TreeNode;

public class L236LowestCommonAncestorOfaBT {
    
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 求解方式:找到从根节点到两个叶子节点pq的路径,根据两条路径找到第一个公共子结点。
        if (root == null || root == p || root == q)
            return root;
        List<TreeNode> path1 = new ArrayList<TreeNode>();
        getPath(root, p, path1);
        List<TreeNode> path2 = new ArrayList<TreeNode>();
        getPath(root, q, path2);
        TreeNode ans = getCommanNode(path1, path2);
        return ans;
    }

    private TreeNode getCommanNode(List<TreeNode> path1, List<TreeNode> path2) {
        // TODO Auto-generated method stub
        int len1 = path1.size();
        int len2 = path2.size();
        int i;
        for (i = 0; i < len1 && i < len2; i++) {
            if (path1.get(i).val != path2.get(i).val) {
                return path1.get(i - 1);
            }
        }
        return path1.get(i - 1);
    }

    public boolean getPath(TreeNode root, TreeNode p, List<TreeNode> path) {
        // TODO 求根节点到p、q结点的路径
        path.add(root);
        if (root == p) {
            return true;
        }

        boolean found = false;
        if (root.left != null) {
            found = getPath(root.left, p, path);
            if (found == true)
                return true;
        }
        if (root.right != null) {
            found = getPath(root.right, p, path);
            if (found == true)
                return true;
        }

        path.remove(root);
        return found;
    }

    public static void main(String[] args) {
        TreeNode n1 = new TreeNode(1);
        TreeNode n2 = new TreeNode(2);
        TreeNode n3 = new TreeNode(3);
        n1.left = null;
        n1.right = n2;
        n2.left = null;
        n2.right = n3;

        TreeNode n4 = null;
        TreeNode n5 = null;
        n3.left = n4;
        n3.right = n5;
        L236LowestCommonAncestorOfaBT l236 = new L236LowestCommonAncestorOfaBT();
        //测试getPath()函数
        List<TreeNode> path1 = new ArrayList<TreeNode>();
        l236.getPath(n1, n3, path1);
        for (int i = 0; i < path1.size(); i++) {
            System.out.println(path1.get(i).val);
        }
        List<TreeNode> path2 = new ArrayList<TreeNode>();
        l236.getPath(n1, n2, path2);
        for (int i = 0; i < path2.size(); i++) {
            System.out.println(path2.get(i).val);
        }
        System.out.println("~~~~~~~~~~~~~~");
        //测试求公共结点函数 getCommanNode()
        TreeNode com = l236.getCommanNode(path1, path2);
        System.out.println("getCom祖先:" + com.val);
        System.out.println("~~~~~~~~~~~~~");
        //lowestCommonAncestor()函数
        TreeNode comTreeNode = l236.lowestCommonAncestor(n1, n2, n3);
        System.out.println("公共祖先为:" + comTreeNode.val);
        TreeNode node1 = new TreeNode(1);
        TreeNode node2 = new TreeNode(2);
        n1.left = null;
        n1.right = n2;
        n2.left = null;
        n2.right = null;
        System.out.println("~~~~~~~~~~~~~~~~~~");
        TreeNode comTreeNode1 = l236.lowestCommonAncestor(node1, node1, node2);
        System.out.println("case2:" + comTreeNode1.val);
    }
}

解法二:递归

在root的左右子树中找p、q,如果left跟right都不为为空,证明p、q分别在左右子树,那么他们的公共祖先就是root。

如果left中有一个为空,那么不为空的那个就是公共祖先。

public TreeNode lowestCommonAncestor2(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 root;
        return left != null ? left : right;
    }

 

posted @ 2018-02-11 22:20  于淼  阅读(199)  评论(0编辑  收藏  举报