题目:求二叉树中任意两个节点的最低公共父节点。
思路:
从根结点开始遍历,判断以当前结点为根的树中左右子树是不是包含我们要找的两个结点。如果两个结点都出现在它的左子树中,那最低的共同父结点必出现在它的左子树中;如果两个结点都出现在它的右子树中,那最低的共同父结点也出现在它的右子树中;如果两个结点一个出现在左子树中,一个出现在右子树中,那当前的结点就是最低的共同父结点。
struct BinaryTreeNode {
int value;
BinaryTreeNode *left;
BinaryTreeNode *right;
}
bool containsNode(BinaryTreeNode *root,BinaryTreeNode *node){
if(root == node)
return true;
bool flag = false;
if(!flag && root->left != NULL)
flag = containsNode(root->left,node);
if(!flag && root->right != NULL)
flag = containsNode(root->right,node);
return flag;
}
BinaryTreeNode *lastCommonParentNode(BinaryTreeNode *root,BinaryTreeNode *node1,BinaryTreeNode *node2){
if(root == NULL || node1 == NULL || node2 == NULL){
return NULL;
}
bool leftsubtreehasnode1 = false;
bool leftsubtreethasnode2 = false;
if(root->left != NULL){
leftsubtreehasnode1 = containsNode(root->left,node1);
leftsubtreehasnode2 = containsNode(root->left,node2);
}
if(leftsubtreehasnode1 && leftsubtreehasnode2){
if(root->left == node1 || root->left == node2)
return root;
return lastCommonParentNode(root->left,node1,node2);
}
bool rightsubtreehasnode1 = false;
bool rightsubtreehasnode2 = false;
if(root->right != NULL){
if(leftsubtreehasnode1){
rightsubtreehasnode1 = containsNode(root->right,node1);
}
if(leftsubtreehasnode2){
rightsubtreehasnode2 = containsNode(root->right,node2);
}
}
if(rightsubtreehasnode1 && rightsubtreehasnode2){
if(root->right == node1 || root->right == node2)
return root;
return lastCommonParentNode(root->right,node1,node2);
}
if((leftsubtreehasnode1 && rightsubtreehasnode2)|| (leftsubtreethasnode2 && rightsubtreehasnode1)){
return root;
}
return NULL;
}
时间复杂度为O(n^2),因为要遍历树中节点两遍,这显然不是最优的。
此题的变种:若每个节点都存有指向父节点的指针,如何求二叉树中任意两节点的最低公共子节点。
思路:此时我们可以把问题转化为两个单链表求第一个公共子节点。
而对于求两个单链表的第一个公共子节点则是我们比较熟悉的。
struct BinaryTreeNode {
int value;
BinaryTreeNode *left;
BinaryTreeNode *right;
}
bool getNodePath(BinaryTreeNode *root,BinaryTreeNode *node,list<BinaryTreeNode*> &path){
if(root == node)
return true;
path.push_back(root);
bool found = false;
if(root->left != NULL)
found = getNodePath(root->left,node,path);
if(!found && root->left != NULL)
found = getNodePath(root->right,node,path);
if(!found)
path.pop_back();
return found;
}
BinaryTreeNode *LastCommonNode(const list<BinaryTreeNode*> &list1,const list<BinaryTreeNode*> &list2){
list<BinaryTreeNode*> list1;
list<BinaryTreeNode*> list2;
list<BinaryTreeNode*>::const_iterator iter1 = list1.begin();
list<BinaryTreeNode*>::const_iterator iter2 = list2.begin();
BinaryTreeNode *lastcommonnode = NULL;
while(iter1 != list1.end() && iter2 != list2.end()){
if(*iter1 == *iter2)
lastcommonnode = iter1;
iter1++;
iter2++;
}
return lastcommonnode;
}
BinaryTreeNode *getLastCommonNode(BinaryTreeNode *root,BinaryTreeNode *node1,BinaryTreeNode *node2){
if(root == NULL || node1 == NULL || node2 == NULL)
return NULL;
list<BinaryTreeNode*> path1;
getNodePath(root,node1,path1);
list<BinaryTreeNode*> path2;
getNodePath(root,node2,path2);
return LastCommonNode(path1,path2);
}