首先,我想让任何人都知道这是一个任务,我已经用O(n)完成了定位前一个前任,但我想用O(log n)来做,我知道这是可能的,因为树是AVL树。
我用O(n)完成它的方法是我根据键(记录)将树分成2,并对左树进行最大搜索,然后搜索右树。我知道它不是log n,因为在我缩小解决方案之后,我仍然需要处理左或右树中的所有节点,所以最多它仍然是1 / 2n。
我可以看到解决方案的模式,但仍然无法理解它。我正在考虑使用root和节点指针,但我仍然不确定如何实现它。
任何指针都会受到赞赏,我已经谷歌搜索并试图解决这个问题几天无济于事。
答案 0 :(得分:2)
给定AVL树中的节点N,有三种情况:
N有一个左子L.然后N的前一个必须是L的最右边最后代。要找到它,你需要下降到L的子树,在每个子树上取右边的分支。子节点。最多可以有log n级别,因此这是O(log n)。
N没有左子,但本身就是父P的正确孩子。那么P必须是前一个,位于O(1)时间。
N没有左子,是父P的左子。然后沿着树走向根,直到找到一个上升的A的正确子节点。如果没有这样的A ,N没有任何前身;否则A是N的直接前身。同样,最多可以检查log n个父级别,所以这也是O(log n)。
确定三个适用中的哪一个显然可以在O(1)时间内完成,因此总时间复杂度为O(log n)。
(实际上,案例2是案例3的一个特例;我在三个案例中写了它,希望能让它更容易理解。)
示例AVL树供参考(这与Wikipedia page for AVL tree上给出的示例相同,但我重新创建了图形而不是复制图像;如果有人,可以从here分叉源代码想做出修改):
节点17和50是情况1的示例;节点23和76是情况2的例子;节点9是没有前任的情况3的示例;节点19是具有前驱的情况3的示例。如果您仔细考虑从上面的树中查看示例的每个案例,您将能够确认这些陈述是正确的。这可能比通过正式证明(尽管如此)更容易。
答案 1 :(得分:0)
我实际上想出了一种更简单的方法来解决这个问题而不使用父指针或子指针。
这是我做的: 当我遍历遍历树时保存每个节点并保存记录小于目标的所有节点。
如果是叶子,则将临时指针返回给调用者。