这是我提出的用于非递归地找到二叉树中两个节点的最低共同祖先的算法。这是基本策略:
我的理解是我的算法的最坏情况时间和空间复杂度是O(log(n)),因为我们从来不需要在我们的hashsets中进行超过2 *个高度遍历或存储超过2 *个高度值(并且由于哈希集和树词典的查找时间是O(1))。
以下是我的代码(C#)。请告知我的分析是否正确,或者是否有更有效(非递归)的方法:
int LowestCommonAncestor(int value1, int value2, Dictionary<int, int> tree)
{
var value1Visited = new HashSet<int>();
var value2Visited = new HashSet<int>();
while (true)
{
if (value1 == value2) return value1;
if (value1Visited.Contains(value2)) return value2;
if (value2Visited.Contains(value1)) return value1;
int nextValue1;
int nextValue2;
if (tree.TryGetValue(value1, out nextValue1))
{
//Walk node 1 up the tree:
value1 = nextValue1;
value1Visited.Add(value1);
}
else
{
//Node doesn't exist in tree:
return -1;
}
if (tree.TryGetValue(value2, out nextValue2))
{
//Walk node 2 up the tree:
value2 = nextValue2;
value2Visited.Add(value2);
}
else
{
//Node doesn't exist in tree:
return -1;
}
}
}
答案 0 :(得分:0)
从每个节点向上移动到根以测量其深度
从较深的节点向上移动路径,直到达到与较浅节点相同的深度。
从两个节点向上移动路径(即在两条路径上保持相同的深度),直到它们相遇为止。
答案 1 :(得分:0)
您不需要两个哈希集。
当D是树的最大深度时,复杂性是O(D)最坏情况的复杂性。
N个节点中最坏情况的复杂性 - 当树在列表中退化时,其中一个节点是该列表的头部,另一个节点是尾部。
如果树是平衡的,则D = log(N) - log的基数是节点的后代数(binary-log2,ternary-log3等)。
答案 2 :(得分:0)
然后,这是我修改过的算法:
int LCA(int value1, int value2, Dictionary<int, int> tree)
{
if (!tree.ContainsKey(value1) || !(tree.ContainsKey(value2))) return -1;
int depth1 = 0;
int depth2 = 0;
int tmpVal1 = value1;
int tmpVal2 = value2;
while (tmpVal1 != -1)
{
tmpVal1 = tree[tmpVal1];
depth1++;
}
while (tmpVal2 != -1)
{
tmpVal2 = tree[tmpVal2];
depth2++;
}
if (depth1 > depth2)
{
while (depth1 > depth2)
{
value1 = tree[value1];
depth1--;
}
}
else if (depth2 > depth1)
{
while (depth2 > depth1)
{
value2 = tree[value2];
depth2--;
}
}
while (value1 != value2)
{
value1 = tree[value1];
value2 = tree[value2];
}
return value1;
}