一、问题描述
对于一颗二叉树,给定其中的两节点n1,n2,求出他们的最低公共祖先(Lowest Common Ancestor )。例如:
二、问题求解
利用递归思想。
(1)从root开始遍历,如果n1和n2中的任一个和root匹配,那么root就是LCA。
(2) 如果都不匹配,则分别递归左、右子树,如果有一个 key(n1或n2)出现在左子树,并
且另一个key(n1或n2)出现在右子树,则root就是LCA.
(3)如果两个key都出现在左子树,则说明LCA在左子树中,否则在右子树。
三、实现代码
时间复杂度为O(n)
#include<iostream>
using namespace std;
typedef int KeyType;
typedef struct BinaryTreeNode
{
KeyType key;
struct BinaryTreeNode *left;
struct BinaryTreeNode *right;
}BTNode, *BiTree;
//创建二叉树节点
BTNode *CreateBTNode(KeyType key)
{
BTNode *node = new BTNode;
node->key = key;
node->left = node->right = NULL;
return node;
}
//对于给定的树中两节点n1和n2,返回两者lca的指针
BTNode *findLCA(BTNode *root, KeyType n1, KeyType n2)
{
if(root == NULL) return NULL;
//(1)n1,n2中的一个是另一个的父节点,即为LCA
if(root->key==n1 || root->key==n2)
return root;
//(2)n1,n2没有父子关系,这时又存在两种情况:
//case1:同在一个子树。case2:分别在两个子树。
BTNode *left_lca=findLCA(root->left, n1, n2);
BTNode *right_lca=findLCA(root->right, n1, n2);
//都为真,说明两边子树都能找到n1或n2,这是case2的情况
if(left_lca && right_lca)
return root;//当n1,n2分别在两个子树时lca即为根节点
//case1的情况
return (left_lca != NULL)?left_lca:right_lca;
}
int main()
{
BTNode *root = CreateBTNode(1);
root->left = CreateBTNode(2);
root->right = CreateBTNode(3);
root->left->left = CreateBTNode(4);
root->left->right = CreateBTNode(5);
root->right->left = CreateBTNode(6);
root->right->right = CreateBTNode(7);
cout <<"LCA(4, 5): "<<findLCA(root, 4, 5)->key<<endl;
cout <<"LCA(4, 6): "<<findLCA(root, 4, 6)->key<<endl;
cout <<"LCA(3, 4): "<<findLCA(root, 3, 4)->key<<endl;
cout <<"LCA(2, 4): "<<findLCA(root, 2, 4)->key<<endl;
return 0;
}
结果:
LCA(4, 5): 2
LCA(4, 6): 1
LCA(3, 4): 1
LCA(2, 4): 2
Process returned 0 (0x0) execution time : 0.279 s
Press any key to continue.