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