二叉树祖先

LCA,lowest common ancestor(二叉树祖先问题0

找出两个节点的最低的公共祖先(LCA,lowest common ancestor)

eg:

     _______3______
    /              \
 ___5__          ___1__
/      \        /      \
6      _2_      0       8
      /   \
     7     4

5和1的公共最低祖先是3;5和4的最低公共祖先是5.

1) 递归的方法:

在先序遍历的基础上改进,遍历时,如果遇到了p或者q,它们分别在不同的子树,那么当前子树的公共的父节点就是最低的根节点。
如果它们在同一子树,那么他们在另一子树上的祖先必是空。

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if(!root) return nullptr;
    if(p==root || q==root) return root;
    TreeNode* left=lowestCommonAncestor(root->left,p,q);
    TreeNode* right=lowestCommonAncestor(root->right,p,q);
    if(left!=nullptr && right!=nullptr) return root;
    return left!=nullptr?left:right;
}

这里的时间复杂度是O(n).

2)找到从根节点到某一节点所经历的路径存起来,找出两路径的最低重合点

对于5和4,有3->5;3->5->->2->4,故重合在5.

//第一步:找到从根节点到某一节点是否存在路径

bool get_path(TreeNode* root, TreeNode* p, vector<TreeNode*> &path) {
if (root == nullptr)
    return false;
if (root == p) {
    path.push_back(p);
    return true;
}   
path.push_back(root);
bool found = 0;
found = get_path(root->left, p, path) || get_path(root->right, p, path);
if (!found) {
    path.pop_back();
}else
    path.push_back(p);
return found;
}

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root) return nullptr;
if (p == root || q == root) return root;
vector<TreeNode*> path1, path2;
get_path(root, p, path1);
get_path(root, q, path2);
int i = 0, n1 = path1.size(), n2 = path2.size();
TreeNode* last = nullptr;
while (i<n1 && i<n2) {
    if (path1[i] == path2[i])
        last = path1[i];
    i++;
}
return last;
}
点赞