LintCode-578: Lowest Common Ancestor III

  1. Lowest Common Ancestor III
    中文English
    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.
Each node has a different value

这题我感觉不算简单。
注意:
1) 因为是找最小祖先,所以递归最远的那个节点如果找到,必须把自身传上来。
2)注意root是A或B的情形。
3)找到A的条件是: 左子树找到A || 右子树找到A || root就是A。
找到B的条件是: 左子树找到B || 右子树找到B || root就是B。
4)如果二叉树里面只有A或只有B的时候,可以返回NULL吗?不行,因为这和二叉树里面没有A也没有B的情况没法区分。
5)这题也可以用Taijan算法(traverse),可能面试用不上,下次学习一下。

代码如下:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */



class Solution {
public:
    /*
     * @param root: The root of the binary tree.
     * @param A: A TreeNode
     * @param B: A TreeNode
     * @return: Return the LCA of the two nodes.
     */

    TreeNode * lowestCommonAncestor3(TreeNode * root, TreeNode * A, TreeNode * B) {
        ReturnType ret = helper(root, A, B);
        if (ret.findA && ret.findB) 
            return ret.node;
        else
            return NULL;
    }

private:

    struct ReturnType {
        bool findA;
        bool findB;
        TreeNode* node;
        ReturnType(bool a=false, bool b=false, TreeNode* c=NULL) : findA(a), findB(b), node(c) {} 
    };
    
    ReturnType helper(TreeNode* root, TreeNode* A, TreeNode* B) {
        if (!root) 
            return ReturnType();
        
        ReturnType leftRet = helper(root->left, A, B);
        ReturnType rightRet = helper(root->right, A, B);
        
        bool findA = leftRet.findA || rightRet.findA || root == A;
        bool findB = leftRet.findB || rightRet.findB || root == B;
        
        if (A == root || B == root) {
            return ReturnType(findA, findB, root);
        }
        
        //now find A and find B, and we know it is not overlapping with root 
        if (leftRet.node && rightRet.node) {
            return ReturnType(true, true, root);
        }

        if (leftRet.node) {
            return ReturnType(findA, findB, leftRet.node);
        }
        
        if (rightRet.node) {
            return ReturnType(findA, findB, rightRet.node);    
        }
        
        return ReturnType(false, false, NULL);
    }
    
};

解法2:其实这题可以直接判断A和B是不是都在tree中,若是,直接递归查找。否则,就返回NULL就可以了。

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */


class Solution {
public:
    /*
     * @param root: The root of the binary tree.
     * @param A: A TreeNode
     * @param B: A TreeNode
     * @return: Return the LCA of the two nodes.
     */
    TreeNode * lowestCommonAncestor3(TreeNode * root, TreeNode * A, TreeNode * B) {
        if (!root || !findNode(root, A) || !findNode(root, B)) return NULL;
        return helper(root, A, B);
    }

private:
    bool findNode(TreeNode * root, TreeNode * node) {
        if (!root) return false;
        if (root == node) return true;
        return findNode(root->left, node) || findNode(root->right, node);
    }
    
    TreeNode * helper(TreeNode * root, TreeNode * A, TreeNode * B) {
        if (!root || root == A || root == B) return root;
        TreeNode * leftFind = helper(root->left, A, B);
        TreeNode * rightFind = helper(root->right, A, B);
        if (leftFind && rightFind) return root;
        return leftFind ? leftFind : rightFind;
    }
};

代码同步在
https://github.com/luqian2017/Algorithm

你可能感兴趣的:(LintCode)