可能重复:
How can I find the common ancestor of two nodes in a binary tree?
first common ancestor of a binary tree
我有一个二叉树,如下所示。我需要找到最不常见的祖先(LCA)。例如,6和4的LCA是1,4和5的LCA是2。
1
/ \
2 3
/ \ / \
4 5 6 7
任何人都可以建议我应该如何处理并解决这个问题?
答案 0 :(得分:15)
从普通的深度优先搜索算法开始:
public Node find(Node node, int target) {
if(node == null || node.value == target) {
return node;
}
if(node.value > target) {
return find(node.left, target);
} else {
return find(node.right, target);
}
}
现在,使其适应两个“目标”参数,target1和target2。
当搜索target1时,你向左走,而搜索target2就是你的,你找到了LCA。
这假设两个目标确实存在。如果你需要声明他们这样做,你需要在找到潜在的LCA后继续搜索。
public Node findLca(Node node, int t1, int t2) {
if(node == null) {
return null;
}
if(node.value > t2 && node.value > t1) {
// both targets are left
return findLca(node.left, t1, t2);
} else if (node.value < t2 && node.value < t1) {
// both targets are right
return findLca(node.right, t1, t2);
} else {
// either we are diverging or both targets are equal
// in both cases so we've found the LCA
// check for actual existence of targets here, if you like
return node;
}
}
答案 1 :(得分:1)
使用列表可以解决您的问题。
你应该制作一个getAncestorList()。它返回其祖先的列表顺序,例如。 4具有祖先List [1,2],并且7具有ancestorList [1,3]
list1 = node1.getAncestorList()
list2 = node2.getAncestorList()
minlength = min(list1.size(), list2.size())
for (int i = 0; i < minlength; i++) {
e1 = list1.getItemAt(i);
e2 = list2.getItemAt(i);
if (e1 == e2) ec = e1;
}
return ec;
因为他们都有相同的根祖先。所以你不需要关心不同的深度。你总能找到顶级(同一位)的祖先。和祖先(n)是最新的共同祖先。
答案 2 :(得分:0)
这是我通常做的事情:
首先计算f[i][j]
,它表示节点2^j
的第i
个父亲。我们有
f[i][j] = f[f[i][j - 1]][j - 1]
现在我们可以在j-th
时间内获得节点i的log(n)
父亲。
我们需要每个节点的深度,比如h[i]
以上可以使用复杂度为dfs()
的简单O(N*Log(N))
完成。
然后对于询问节点(i)和节点(j)的LCA的每个查询(i,j),想象两只猴子在树中起床,尝试获取到同一节点。
您可以参考:
int query(int u, int v){
if(h[u]>h[v])swap(u,v);
v = getUp(v,h[v]-h[u]);
for(int i=log(n);i>=0;i--){
if(f[u][i]!=f[v][i]){
u=f[u][i];
v=f[v][i];
}
}
while(u!=v){
u=f[u][0];
v=f[v][0];
}
return u;
}
这里getUp(i, j)
意味着找到节点i的j-th
父亲,如上所述,可以
int nt(int u,int x){
for(int i=log(n);i>=0;i--){
if((1<<i)<=x){
u=f[u][i];
x-=(1<<i);
}
}
return u;
}
因此,对于非常查询,复杂性也是O(N*Log(N))
。