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);   //写成   return ReturnType(findA, findB, 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值