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; }