tan*_*nia 5 java algorithm binary-search-tree
我正在准备技术面试,所以基本上从一开始就学习算法:)我们给了一个BST.我需要在其中找到desc路径的最大长度,它始终向左或向右.换句话说,示例树的下行路径为2,即15-10-6
5
/ \
2 15
/
10
/ \
6 14
Run Code Online (Sandbox Code Playgroud)
我对算法问题很陌生.我解决这个问题的步骤是什么?
我的想法是使用DFS和计数器来存储最长的路径.但我无法弄清楚如何使用递归来完成这项工作,而递归对于这种数据结构来说似乎更自然.
有什么建议/指示吗?
措辞有点令人困惑,但我认为你的意思是最大的
您可以通过两次传递执行此操作,一次查找最大左侧路径,另一次查找最大右侧路径(然后取这两个中的最大值).或者你可以一次完成两个任务.
对于每个节点,您想要知道三个值:
如果你以递归方式执行此操作,这意味着递归应该返回这三个值,可能是一个小数组或一个简单的三字段对象.
这看起来像
Results calculate(Tree node) {
if (node == null) return new Results(0,0,0);
else {
Results leftResults = calculate(node.left);
Results rightResults = calculate(node.right);
int leftLength = 1 + leftResults.leftLength;
int rightLength = 1 + rightResults.rightLength;
int maxLength = Math.max(Math.max(leftLength, rightLength),
Math.max(leftResults.maxLength, rightResults.maxLength));
return new Results(leftLength, rightLength, maxLength);
}
}
Run Code Online (Sandbox Code Playgroud)
而整体结果就是calculate(root).maxLength.
实际上,这是我测试的Codibility问题.我只是为了讨论它而提到一个非递归的解决方案.
树本身具有可以修改的值.
我找到了一个比递归解决方案更好的解决方案,但是我不用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 reminder = currNode.x % 100000;
if (currNode.l != null)
{
currNode.l.x = 1 + reminder;
maxLength = Math.Max(maxLength, currNode.l.x);
toProcess.Add(currNode.l);
}
if (currNode.r != null)
{
currNode.r.x = 100000 + (currNode.x - reminder);
maxLength = Math.Max(maxLength, currNode.r.x / 100000);
toProcess.Add(currNode.r);
}
}
return maxLength;
}
}
Run Code Online (Sandbox Code Playgroud)
如果你计时,这比复数更快.想法是在每个节点,您在子节点中存储更长的长度,并将它们附加到列表(您可以使用堆栈,如果您需要)以后处理.您使用int来存储计数.Codibility的最初问题是,节点数不超过10000个,最大深度为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;
}
Run Code Online (Sandbox Code Playgroud)