[leetcode] LowestCommonAncestor

LowestCommonAncestor

  • 問題描述:給定一顆二叉樹,和二叉樹的兩個節點,計算出這兩個節點的最低公公祖先。
  • 解法1:
    • 最低公公祖先可能出現的最高值就是根節點。
    • 我們找到從根節點到兩個節點的路徑,path1和path2.
    • 則兩者一定是Y字型或者是V字形(root節點)
    • 則我們就把問題轉化成了計算兩個list的相交點問題。
    • 首先長的path先走他們之間長度差值步,使得後續的兩個path長度一致。
    • 然後再同時向後走,第一個相遇的點就是LCA
  • 解法2 (DP):
    • 拆分子問題:我們可以判斷左子樹和右子樹是否包含這兩個節點其中的一個。
    • 構造父問題:如果左子樹和右子樹都包含兩個節點中的一個,則返回當前的根節點。如果只有左子樹包含,則返回左子樹的根節點,如果只有右子樹包含,則返回右子樹的根節點。
  • 代碼
bool findPath(TreeNode* root, TreeNode* target, vector<TreeNode*>& path){
        if(root == NULL){
            return false;
        }
        if(root == target){
            path.push_back(root);
            return true;
        }
        bool left_res = findPath(root->left, target, path);
        if(left_res){
            path.push_back(root);
            return true;
        }
        bool right_res = findPath(root->right, target, path);
        if(right_res){
            path.push_back(root);
            return true;
        }
        return false;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == NULL)
            return NULL;
        vector<TreeNode*> path_p, path_q;
        findPath(root, p, path_p);
        findPath(root, q, path_q);
        if(path_p.empty() || path_q.empty())
            return NULL;
        int size_p = (int) path_p.size();
        int size_q = (int) path_q.size();
        int start_p = 0;
        int start_q = 0;
        if(size_p >= size_q){
            start_p = size_p - size_q;
        }else{
            start_q = size_q - size_p;
        }
        for(;start_p < size_p && start_q < size_q;start_p++, start_q++){
            if(path_p[start_p] == path_q[start_q])
                return path_p[start_p];
        }
        return NULL;
    }
    TreeNode* lowestCommonAncestorV2(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root || root == p || root == q)
            return root;
        TreeNode* left = lowestCommonAncestorV2(root->left, p, q); // 在左孩子中找尋找q或者p
        TreeNode* right = lowestCommonAncestorV2(root->right, p, q); // 在右子樹中嘗試尋找p或者q
        // 如果左孩子找到了,右孩子沒找打,則是左孩子
        // 如果兩個都找到了,則是root
        return left == NULL ? right: right == NULL ? left : root;
        // return !left ? right : !right ? left : root;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章