Lowest Common Ancestor of a Binary Tree
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.
解题思路
思路一:自上而下(top-down)地访问每个节点。首先,如果当前节点是
p
或
- 若
totalMatches=0
,则在当前结点的右子树中寻找
p
和
q 的 LCA; - 若
totalMatches=1
,则当前结点必为
p
和
q 的 LCA; - 若
totalMatches=2
,则在当前结点的左子树中寻找
p
和
q 的 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 {
private:
int countMatchesPQ(TreeNode *root, TreeNode *p, TreeNode *q) {
if (root == NULL) return 0;
int matches = countMatchesPQ(root->left, p, q) + countMatchesPQ(root->right, p, q);
if (root == p || root == q) {
return matches + 1;
}
return matches;
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == NULL || p == NULL || q == NULL) return NULL;
if (root == p || root == q) return root;
int totalMatches = countMatchesPQ(root->left, p, q);
if (totalMatches == 0) {
return lowestCommonAncestor(root->right, p, q);
}
else if(totalMatches == 1) {
return root;
}
else {
return lowestCommonAncestor(root->left, p, q);
}
}
};
思路二:使用自底向上(bottom-up)的方法,可以避免思路一中自上而下(top-down)的方法对相同子树重复访问的问题。
树的recursive算法不一定要先判断当前节点再判断子树,如果子树的信息对于当前节点有> 用,则可以颠倒顺序变成bottom-up的方式。树的bottom-up方式和top-down方式的主> 要差别就在于:先处理当前节点还是先处理子树。
代码如下:
/**
* 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 == NULL) return NULL;
if (root == p || root == q) return root;
TreeNode *L = lowestCommonAncestor(root->left, p, q);
TreeNode *R = lowestCommonAncestor(root->right, p, q);
// if p and q are on both sides
if (L != NULL && R != NULL) return root;
// either one of p,q is on one side OR p,q is not in L&R subtrees
return (L != NULL) ? L : R;
}
};
思路三:分别记录从根节点到
p
和
/**
* 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 {
private:
bool getPath(TreeNode *root, TreeNode *target, vector<TreeNode *> &path) {
if (root == NULL) return false;
path.push_back(root);
if (root != target) {
if (!getPath(root->left, target, path)) {
if (!getPath(root->right, target, path)) {
path.pop_back();
return false;
}
}
}
return true;
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
vector<TreeNode *> path1, path2;
getPath(root, p, path1);
getPath(root, q, path2);
TreeNode *LCA= NULL;
int maxLen = min(path1.size(), path2.size());
for (int i = 0; i < maxLen; ++i) {
if (path1[i] == path2[i])
LCA = path1[i];
else
break;
}
return LCA;
}
};
思路四:带父节点的情况?