在BST中找到每个级别的最大元素。
[1] In O(n) time and O(1) space
[2] In O(logn) time and O(n) space
编辑:@Imposter发布的解决方案适用于[1] 这是[1]
的解决方案private int level = 0;
private int VisitedLevels = -1;
public void findLargestByLevel(AvlNode root)
{
if(root == null) return;
else
{
if(level > VisitedLevels)
{
System.out.println(root.data + " @ Level = " + level);
VisitedLevels++;
}
level++;
findLargestByLevel(root.right);
findLargestByLevel(root.left);
level--;
}
}
但我仍然无法找到[2]
的解决方案我想到的方法:如果我们预处理树并将其展平,就像树的序列化一样,
100
50 200
20 75
#L0, 100, #L1, 50, 200, #L2, 20, 75, #L3
#L是级别的标记:
然后我们可以轻松回答O(1)时间内最高和最低等级的查询, 此外,如果树被修改,我们可以在LogN时间内从序列化数据执行插入和删除。 请为[2]推荐某人,虽然在我看来zit看起来无法实现[2],但我想听听别人的建议
答案 0 :(得分:6)
如果BST是完全BST,则可以在log(N)时间内完成,因为您需要做的就是一直向右移动(因为右侧的元素总是比左侧更大。)如果是因为我们不确定右子树的高度总是大于左子树,所以我们不得不遍历所有元素。
示例:如果右子树有两个级别,左子树有三个级别,那么使用上面的方法我们可以打印最大值到两级但我们错过了右子树中不存在的第三级。
因此,如果时间复杂度不是完全BST,则时间复杂度最小为O(n),如果没有给出额外空间,则时间复杂度可能更高。
如果你做BFS,它只需要O(n)时间复杂度和O(n)空间复杂度。如果你想使用DFS,那么下面的算法将帮助你在O(n)时间复杂度和O(h),其中h是树的高度。
采用全局变量计数器,表示到目前为止遍历的最大级别数。
当您对左子树增量进行递归调用时,取两个变量 L 和 R L
同样,当您对右子树增量进行递归调用时 R 。
为每个给出级别编号的节点找到 L 和 R 的最大值。
当遍历时节点的最大值增加( L,R )时,如果计数器小于计数器,请使用计数器进行检查max( L,R )然后分配内存并初始化为零并递增计数器。(这意味着我们实际上是为树中的每个级别创建变量)。
在遍历时,我们将每次检查高度或级别变量,并将其与正在考虑的当前节点(如果当前节点大于Level变量)进行比较,然后使用正在考虑的节点更新级别变量。
遍历打印高度或级别变量后。
答案 1 :(得分:-1)
[1]这可以通过遍历每个级别并保持最大记录来迭代完成。 这可以通过一个简单的BFS来完成(假设你也不计算存储中的递归级别变量)。例如。由简单队列替换的递归将比O(1)存储花费更多,在这种情况下,除非节点按级别排序,否则这对我来说似乎是不可能的。
[2]二元树具有右子的属性大于左边所以如果你每次只穿过最右边的孩子(除非它不存在,然后带左子)你可以得到log(n)中的最大值时间。我不确定它是否需要O(n)存储。