非递归解决方案
实际上,这是我经过测试的可编码性问题。为了讨论它,我只是提到了一个非递归解决方案。
树本身有一个可以修改的值。
我在这里找到了比递归解决方案更好的解决方案,但我没有用 Java 编程,所以我将使用正确算法的 C# 解决方案:
public class Tree
{
public int x;
public Tree l;
public Tree r;
}
class solution
{
public int solution(Tree T)
{
// write your code in C# 5.0 with .NET 4.5 (Mono)
List<Tree> toProcess = new List<Tree>(10000);
if (T == null)
return 0;
int maxLength = 0;
T.x = 0;
toProcess.Add(T);
while (toProcess.Count != 0)
{
Tree currNode = toProcess[toProcess.Count-1];
toProcess.RemoveAt(toProcess.Count - 1);
int remainder = currNode.x % 100000;
if (currNode.l != null)
{
currNode.l.x = 1 + remainder;
maxLength = Math.Max(maxLength, currNode.l.x);
toProcess.Add(currNode.l);
}
if (currNode.r != null)
{
currNode.r.x = 100000 + (currNode.x - remainder);
maxLength = Math.Max(maxLength, currNode.r.x / 100000);
toProcess.Add(currNode.r);
}
}
return maxLength;
}
}
如果你计时的话,这比乘数回避要快。这个想法是在每个节点上,您在子节点中存储更长的长度并将它们附加到列表中(如果需要,您可以使用堆栈)以供稍后处理。您使用 int 来存储计数。Codibility 上的原始问题提到不超过 10 000 个节点,最大深度为 800。
最后一个优化是用二进制移位替换我使用 100000 来分隔左右长度,这会更快,即使用 16 个第一位存储左侧的长度,其余的用于存储右侧的长度,但我没有当我开始使用递归方法时,有足够的时间来做这件事。
编辑:我做了按位的,太糟糕了,我没有时间确保它是正确的并提交它,因为它比递归的快得多:
public int solution(Tree T)
{
// write your code in C# 5.0 with .NET 4.5 (Mono)
List<Tree> toProcess = new List<Tree>(10000);
int rightmask = 0x0000FFFF;
int leftmask = ~0x0000FFFF;
if (T == null)
return 0;
int maxLength = 0;
T.x = 0;
toProcess.Add(T);
while (toProcess.Count != 0)
{
Tree currNode = toProcess[toProcess.Count-1];
toProcess.RemoveAt(toProcess.Count - 1);
if (currNode.l != null)
{
int leftpart = (currNode.x & leftmask) >> 16;
int newLength = 1 + leftpart;
currNode.l.x = newLength << 16;
maxLength = Math.Max(maxLength, newLength);
toProcess.Add(currNode.l);
}
if (currNode.r != null)
{
int rightpart = (currNode.x & rightmask);
currNode.r.x = 1 + rightpart;
maxLength = Math.Max(maxLength, currNode.r.x);
toProcess.Add(currNode.r);
}
}
return maxLength;
}