Categories
不学无术

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.

思路1

找两个节点的公共最小祖先,可以利用递归的思想,即假设我们有个函数,能判断root为根节点的子树里有几个符合的节点(0,1或2个),在递归跳出的过程中,一旦我们发现有返回2个节点的,那这个根元素就肯定是p和q的最低公共节点了。

思路2

假设要找的节点是5和1,那么从根节点通往5的路径是3->5,通往1的路径是3->1。可以用递归方法构造一个路径栈,比较容易地找到路径,然后就变成两条路径的最长公共节点的问题了,“分岔”的地方就是LCA.
相比思路1,这个方法实施起来简单一些,但是要遍历两遍树,会稍微慢一点。

代码1

* struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int LCASub(TreeNode* root, TreeNode* p, TreeNode* q, TreeNode*& retNode){
        //If we find p or q, return 1
        //If we find root contains p and q, return 2 and set the retNode to common node
        //Else return 0
        if(root == NULL)
            return 0;
        int leftRet = LCASub(root->left, p, q, retNode);
        if(leftRet == 2)
            return 2;
        int rightRet = LCASub(root->right, p, q, retNode);
        if(rightRet == 2){
            return 2;
        }
        if(leftRet + rightRet == 2){
            retNode = root;
            return 2;
        } else if(root == p || root == q){
            if(leftRet==1 || rightRet == 1){
                retNode = root;
                return 2;
            } else {
                return 1;
            }
        } else {
            return leftRet + rightRet;
        }
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        TreeNode* retVal = NULL;
        LCASub(root, p, q, retVal);
        return retVal;
    }
};

代码2

class Solution {
public:
    bool getPath(TreeNode* root, TreeNode* p, stack<TreeNode*>& path){
        //Get path from root to p
        //If not available, return false
        if(root == NULL || root == p){
            path.push(root);
            return true;
        }
        bool foundPath = false;
        if(root->left != NULL){
            //try left
            foundPath = getPath(root->left, p, path);
            if(foundPath){
                //Mission complete, push current node and return
                path.push(root);
                return true;
            }
        }
        if(root->right != NULL){
            foundPath = getPath(root->right, p, path);
            if(foundPath){
                path.push(root);
                return true;
            }
        }
        return false;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> pPath;
        stack<TreeNode*> qPath;
        getPath(root, p, pPath);
        getPath(root, q, qPath);
        TreeNode* result = NULL;
        while(!pPath.empty() && !qPath.empty()){
            if(pPath.top() != qPath.top())
                break;
            result = pPath.top();
            pPath.pop();
            qPath.pop();
        }
        return result;
    }
};