题目
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.
思路1
找两个节点的公共最小祖先,可以利用递归的思想,即假设我们有个函数,能判断root为根节点的子树里有几个符合的节点(0,1或2个),在递归跳出的过程中,一旦我们发现有返回2个节点的,那这个根元素就肯定是p和q的最低公共节点了。
思路2
假设要找的节点是5和1,那么从根节点通往5的路径是3->5,通往1的路径是3->1。可以用递归方法构造一个路径栈,比较容易地找到路径,然后就变成两条路径的最长公共节点的问题了,“分岔”的地方就是LCA.
相比思路1,这个方法实施起来简单一些,但是要遍历两遍树,会稍微慢一点。
代码1
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int LCASub(TreeNode* root, TreeNode* p, TreeNode* q, TreeNode*& retNode){
//If we find p or q, return 1
//If we find root contains p and q, return 2 and set the retNode to common node
//Else return 0
if(root == NULL)
return 0;
int leftRet = LCASub(root->left, p, q, retNode);
if(leftRet == 2)
return 2;
int rightRet = LCASub(root->right, p, q, retNode);
if(rightRet == 2){
return 2;
}
if(leftRet + rightRet == 2){
retNode = root;
return 2;
} else if(root == p || root == q){
if(leftRet==1 || rightRet == 1){
retNode = root;
return 2;
} else {
return 1;
}
} else {
return leftRet + rightRet;
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
TreeNode* retVal = NULL;
LCASub(root, p, q, retVal);
return retVal;
}
};
代码2
class Solution {
public:
bool getPath(TreeNode* root, TreeNode* p, stack<TreeNode*>& path){
//Get path from root to p
//If not available, return false
if(root == NULL || root == p){
path.push(root);
return true;
}
bool foundPath = false;
if(root->left != NULL){
//try left
foundPath = getPath(root->left, p, path);
if(foundPath){
//Mission complete, push current node and return
path.push(root);
return true;
}
}
if(root->right != NULL){
foundPath = getPath(root->right, p, path);
if(foundPath){
path.push(root);
return true;
}
}
return false;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
stack<TreeNode*> pPath;
stack<TreeNode*> qPath;
getPath(root, p, pPath);
getPath(root, q, qPath);
TreeNode* result = NULL;
while(!pPath.empty() && !qPath.empty()){
if(pPath.top() != qPath.top())
break;
result = pPath.top();
pPath.pop();
qPath.pop();
}
return result;
}
};