Java 在二叉树中寻找最小公共祖先
可能重复:Java 在二叉树中寻找最小公共祖先,java,algorithm,tree,binary-tree,Java,Algorithm,Tree,Binary Tree,可能重复: 我有一个二叉树,如下所示。我需要找到最不常见的祖先(LCA)。e、 g 6和4的LCA为1,4和5的LCA为2 1 / \ 2 3 / \ / \ 4 5 6 7 谁能建议我应该如何处理和解决这个问题 使用列表可以解决您的问题 您应该创建一个getAncestorList()。它按其祖先返回一个列表顺序,例如4有一个祖先列表[1,2],7有一个祖先列表[1,3] list1 = node1.getAncestorList() list2 = nod
我有一个二叉树,如下所示。我需要找到最不常见的祖先(LCA)。e、 g 6和4的LCA为1,4和5的LCA为2
1
/ \
2 3
/ \ / \
4 5 6 7
谁能建议我应该如何处理和解决这个问题 使用列表可以解决您的问题 您应该创建一个getAncestorList()。它按其祖先返回一个列表顺序,例如4有一个祖先列表[1,2],7有一个祖先列表[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;
list1=node1.getAncestorList()
list2=node2.getAncestorList()
minlength=min(list1.size(),list2.size())
对于(int i=0;i
因为它们都有相同的根祖先。所以你不需要关心不同的深度。您总是可以找到最上面的(n)个相同的祖先。祖先(n)是最新的共同祖先。我通常会这样做: 首先计算
f[i][j]
,它表示节点i
的第二个父节点2^j
。我们有
f[i][j] = f[f[i][j - 1]][j - 1]
现在我们可以在log(n)
time中获得节点i的j-th
父节点
我们需要每个节点的深度,比如说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;
}
intnt(intu,intx){
对于(int i=log(n);i>=0;i--){
如果((1从普通深度优先搜索算法开始:
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后继续搜索
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;
}
}
公共节点findLca(节点节点,int t1,int t2){
if(node==null){
返回null;
}
if(node.value>t2&&node.value>t1){
//两个目标都留下了
返回findLca(node.left,t1,t2);
}else if(node.value
像这样的问题无非是一个有争议的问题。你愿意走多远?在该领域阅读几篇论文是否合适?添加库依赖项会产生太多开销?是吗?这会继续吗?你做得比(A)找到从根节点到每个节点的路径(b)更好识别两条路径中最长的公共前缀(前缀中的最后一个顶点是最近的公共祖先)。如果两个输入节点不在同一深度,该怎么办?您需要一种方法来确定两个祖先列表发散的位置。@chepner,简单地说,“比较每个元素”步骤需要处理不同长度的列表。这是“查找这两个列表中存在的最大数字”最小的公共元素。我们确定每个节点都有唯一的数字吗?如果没有,第一个公共祖先的每个子树中可能有相同的数字。是的,让我们小心我们所说的“数字”是什么意思“.OP图中的节点ID总是以1作为根,但你是对的,最小的公共值。我们可以确定节点对象是唯一的。我认为上面的“数字”只是不同节点的一个简短名称。我非常喜欢你的解释。但是在find方法中,你不应该让if(Node==null)返回null;?@Student我有if(Node==null)返回节点
,这是等效的。这不是假设树是BST吗?这没有回答问题。您正在执行深度优先搜索,这在尝试获取节点的祖先时没有意义,因为您需要遍历节点的父节点以获得LCA算法。DPS遍历节点的子节点。LCA问题是获取leas它不是共同的祖先,所以你必须穿越父母。