Sunday, April 28, 2019

Lintcode 578. Lowest Common Ancestor III

Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes.
The lowest common ancestor is the node with largest depth which is the ancestor of both nodes.
Return null if LCA does not exist.

Example

Example1
Input: 
{4, 3, 7, #, #, 5, 6}
3 5
5 6
6 7 
5 8
Output: 
4
7
7
null
Explanation:
  4
 / \
3   7
   / \
  5   6

LCA(3, 5) = 4
LCA(5, 6) = 7
LCA(6, 7) = 7
LCA(5, 8) = null

Example2
Input:
{1}
1 1
Output: 
1
Explanation:
The tree is just a node, whose value is 1.

Notice

node A or node B may not exist in tree.
Solution 1: Two pass
/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */


public class Solution {
    /*
     * @param root: The root of the binary tree.
     * @param A: A TreeNode
     * @param B: A TreeNode
     * @return: Return the LCA of the two nodes.
     */
    public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode A, TreeNode B) {
        // write your code here
        if (root == null) {
            return null;
        }
        
        if (doesExistInTree(root, A) == false || doesExistInTree(root, B) == false) {
            return null;
        }
        
        return lowestCommonAncestor3Helper(root, A, B);
    }
    
    private TreeNode lowestCommonAncestor3Helper(TreeNode root, TreeNode A, TreeNode B) {
        if (root == null || root == A || root == B) {
            return root;
        }
        
        TreeNode left = lowestCommonAncestor3Helper(root.left, A, B);
        TreeNode right = lowestCommonAncestor3Helper(root.right, A, B);
        
        if (left != null && right != null) {
            return root;
        }
        
        if (left != null) {
            return left;
        }
        
        if (right != null) {
            return right;
        }
        
        return null;
    }
    
    private boolean doesExistInTree(TreeNode root, TreeNode A) {
        if (root == null) {
            return false;
        }
        
        if (root == A) {
            return true;
        }
        
        boolean left = doesExistInTree(root.left, A);
        boolean right = doesExistInTree(root.right, A);
        
        return left || right;
    }
}
Solution 2: One-pass Solution
/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */


public class Solution {
    /*
     * @param root: The root of the binary tree.
     * @param A: A TreeNode
     * @param B: A TreeNode
     * @return: Return the LCA of the two nodes.
     */
    public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode A, TreeNode B) {
        // write your code here
        if (root == null || A == null || B == null) {
            return null;
        }
        
        ResultType ans = lowestCommonAncestor3Helper(root, A, B);
        
        if (ans.hasA && ans.hasB) {
            return ans.node;
        }
        
        return null;
    }
    
    private ResultType lowestCommonAncestor3Helper(TreeNode root, TreeNode A, TreeNode B) {
        if (root == null) {
            return new ResultType(false, false, null);
        }
        
        ResultType left = lowestCommonAncestor3Helper(root.left, A, B);
        ResultType right = lowestCommonAncestor3Helper(root.right, A, B);
        
        boolean hasA = root == A || left.hasA || right.hasA;
        boolean hasB = root == B || left.hasB || right.hasB;
        
        if (root == A || root == B) {
            return new ResultType(hasA, hasB, root);
        }
        
        if (left.node != null && right.node != null) {
            return new ResultType(hasA, hasB, root);
        }
        
        if (left.node != null) {
            return new ResultType(hasA, hasB, left.node);
        }
        
        if (right.node != null) {
            return new ResultType(hasA, hasB, right.node);
        }
        
        return new ResultType(hasA, hasB, null);
    }
}

class ResultType {
    boolean hasA;
    boolean hasB;
    TreeNode node;
    
    public ResultType(boolean hasA, boolean hasB, TreeNode node) {
        this.hasA = hasA;
        this.hasB = hasB;
        this.node = node;
    }
}

No comments:

Post a Comment