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);
TreeNode* right = lowestCommonAncestorV2(root->right, p, q);
return left == NULL ? right: right == NULL ? left : root;
}