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;
    }
};


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