Leetcode 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.


解题思路:

本题寻找是binary tree的LCA, 因此难度比binary search tree 增大了。很容易出错,也很容易想不清楚,记住!!

两种方法:
1. recursion

A Bottom-up Approach (Worst case O(n) ):

Using a bottom-up approach, we can improve over the top-down approach by avoiding traversing the same nodes over and over again.

We traverse from the bottom, and once we reach a node which matches one of the two nodes, we pass it up to its parent. The parent would then test its left and right subtree if each contain one of the two nodes. If yes, then the parent must be the LCA and we pass its parent up to the root. If not, we pass the lower node which contains either one of the two nodes (if the left or right subtree contains either p or q), or NULL (if both the left and right subtree does not contain either p or q) up.

2. use two stacks, find two nodes separately and compare their traces, the LCA will be the first element to push into its stack, the LCA's parent, till the root. When pop(), you will from root to child....When find the first different node, the node before it will be the LCA of p and q. 


Java code:

1. recursion:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //recursion
        if(root == null || root == p || root == q) { return root; }
        TreeNode l = lowestCommonAncestor(root.left, p, q);
        TreeNode r = lowestCommonAncestor(root.right, p, q);
        if(l!=null && r!= null) return root; // if p and q are on both sides
        return (l!=null)? l: r; //either one of p, q is on one side OR p,q is not in l&r subtrees
    }
}

2. use two stacks

public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        Stack<TreeNode> sp = new Stack<TreeNode>();
        Stack<TreeNode> sq = new Stack<TreeNode>();
        findNode(root, p, sp);
        findNode(root, q, sq);
        TreeNode target = root;
        TreeNode temp;
        while(!sp.isEmpty() && !sq.isEmpty()){
            temp = sp.pop();
            if(temp == sq.pop()) {
                target = temp;
            }
            else{
                break;
            }
        }
        return target;
    }
    
    public boolean findNode(TreeNode root, TreeNode p, Stack<TreeNode> s) {
        if(root == null) {
            return false;
        }
        if(root == p) {
            s.push(root);
            return true;
        }else if(findNode(root.left, p, s) || findNode(root.right, p,s)) {
            s.push(root);
            return true;
        }else{
            return false;
        }
    }
}

Reference:

1. http://articles.leetcode.com/2011/07/lowest-common-ancestor-of-a-binary-tree-part-i.html

2. https://leetcode.com/discuss/49255/share-my-java-solution-using-stack-easy-to-understand

原文地址:https://www.cnblogs.com/anne-vista/p/4815076.html