最近公共祖先(转载)
1、暴力对待
如果是二叉查找树:寻找节点u, v 的最近公共祖先 步骤
1、如果当前结点t 大于结点u、v,说明u、v都在t 的左侧,所以它们的共同祖先必定在t 的左子树中,
故从t 的左子树中继续查找;
2、如果当前结点t 小于结点u、v,说明u、v都在t 的右侧,所以它们的共同祖先必定在t 的右子树中,
故从t 的右子树中继续查找;
3、如果当前结点t 满足 u <t < v,说明u和v分居在t 的两侧,故当前结点t 即为最近公共祖先;
4、而如果u是v的祖先,那么返回u的父结点,同理,如果v是u的祖先,那么返回v的父结点。
示例:
public int query(Node t, Node u, Node v) { int left = u.value; int right = v.value; //二叉查找树内,如果左结点大于右结点,不对,交换 if (left > right) { int temp = left; left = right; right = temp; } while (true) { //如果t小于u、v,往t的右子树中查找 if (t.value < left) { t = t.right; //如果t大于u、v,往t的左子树中查找 } else if (t.value > right) { t = t.left; } else { return t.value; } } }
二、普通的二叉树
如果每个结点都有一个指针指向它的父结点,于是我们可以从任何一个结点出发,得到一个到达树根结点的单向链表。因此这个问题转换为两个单向链表的第一个公共结点。如果给出根节点,LCA问题可以用递归很快解决。而关于树的问题一般都可以转换为递归(因为树本来就是递归描述),参考代码如下:
node getLCA(node root , node node1, node node2)
{
if(root==null) return null;
if(root==node1 || root==node2) return root;
node left=getLCA(root.left, node1,node2);
node right=getLCA(root.right , node1,node2);
if(left != null && right != null)
return
root;
else
if
(left != null)
不论是针对普通的二叉树,还是针对二叉查找树,上面的解法有一个很大的弊端就是:如需N 次查询,则总体复杂度会扩大N 倍,故这种暴力解法仅适合一次查询,不适合多次查询。
return left;
else if (right != null)
return right;
else
return null;
}
后面的链接有更多的内容!
转载自:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.03.md