我有一个基础数组,包含[0到N-1]个元素,每个元素都是一个结构体,其中索引始终指向数组中较早的位置。
在一个更大的算法中的某个时刻,我想要找到节点X和之后任何节点之间的特定C个最低公共祖先。
int LCA(a, b) {
while (a != b) {
if (a > b) {
a = nodes[a].parent;
} else {
b = nodes[b].parent;
}
}
return a;
}
for (y = x + 1; y < n; ++y) {
if (LCA(x, y) == c) {
//other code
}
}
上面的代码其实是伪代码。我通过生成一个查找表来略微提高LCA()的性能。类似这样:
int LCA(a, b) {
if (lookup[a, b]) {
return lookup[a, b];
}
oa = a; ob = b;
while (a != b) {
if (a > b) {
a = nodes[a].parent;
} else {
b = nodes[b].parent;
}
}
lookup[oa, ob] = a;
lookup[ob, oa] = a;
return a;
}
我知道可能有一种方法可以创建一些特殊的LCA()函数,即以某种方式替换上述所有代码,使其专门化,从而使其速度更快。但我还没有想到任何有趣的解决方案。
我尝试过检查C和Y之间是否存在LCA检查,即检查LCA(c, y) == LCA(x, y)
,但当然这是不准确的。
简要概括一下: X始终小于Y。 C始终小于X(因此也小于Y)。父节点始终在比它们的子节点更低的索引处(因此有序)。
节点知道它们的深度是否有帮助呢?
此代码占整个算法80%的CPU时间,总共需要大约4分钟。解决此问题将轻松改善整个算法。谢谢!
O(n^2)
的内存开销,使插入变得更慢,并且似乎不是一件容易的事情。(假设你所说的“查找表”是指“哈希表”。如果不是,我会使用哈希表。) - millimoose