Lowest Common Ancestor of a Binary Tree -- leetcode

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. 先在左子树找LCA;再在右子树找LCA。 返回过程中,如果没有找到LCA,找到p, 或者q,也将其返回。

2. 如果左右子树,返回值都不为空,则本节点为LCA。  说明p,q 分别在左,右子树,或者相反。


要注意的事,此题有个陷阱,比较节点,要比较指针值,而不能比较指指向的val字段。比如不能 root->val == p-val , 而要 root == p。

因为测试用例中,有大量重复的val。也就意味着LCA不唯一了。


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (!root || root == p || root == q)
            return root;
        
        auto left = lowestCommonAncestor(root->left, p, q);
        auto right = lowestCommonAncestor(root->right, p, q);
        if (left && right)
            return root;
        else
            return left ? left : right;
    }
};


算法二,先序遍历

在进行先序遍历中,

1.访问本结点和左子树,右子树后,发现p, q值已经找到,则本节点就是LCA


class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        bool flagp = false, flagq = false;
        return dfs(root, p, q, flagp, flagq);
    }
    
    TreeNode* dfs(TreeNode* root, TreeNode* p, TreeNode* q, bool& flagp, bool& flagq) {
        if (!root)
            return root;
            
        auto flagp_ = flagp;
        auto flagq_ = flagq;
        flagp = root == p ? !flagp : flagp;
        flagq = root == q ? !flagq : flagq;
        auto left = dfs(root->left, p, q, flagp, flagq);
        auto right = dfs(root->right, p, q, flagp, flagq);
        if (left || right)
            return left ? left : right;
        if (flagp_ != flagp && flagq_ != flagq)
            return root;
        return NULL;
    }
};


也可以稍作改进一下,如果访问本节点和左子树已经找到LCA时,不再访问右子树了。如下:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        bool flagp = false, flagq = false;
        return dfs(root, p, q, flagp, flagq);
    }
    
    TreeNode* dfs(TreeNode* root, TreeNode* p, TreeNode* q, bool& flagp, bool& flagq) {
        if (!root)
            return root;
            
        auto flagp_ = flagp;
        auto flagq_ = flagq;
        flagp = root == p ? !flagp : flagp;
        flagq = root == q ? !flagq : flagq;
        auto ans = dfs(root->left, p, q, flagp, flagq);
        if (ans)
            return ans;
        if (flagp_ != flagp && flagq_ != flagq)
            return root;
            
        ans = dfs(root->right, p, q, flagp, flagq);
        if (ans)
            return ans;
        if (flagp_ != flagp && flagq_ != flagq)
            return root;
        return NULL;
    }
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章