找到在BST中添加到k的节点对

时间:2014-07-26 17:06:27

标签: c data-structures

这是一个面试问题。 给定完整的BST,找到其值加到给定总和k的所有节点对。不应使用额外的空间,时间应为O(n),并且不允许进行最佳修改。 采访者花了15分钟提出了算法和代码。 我能够看到其他解决方案但无法找到任何满足给定约束的解决方案

2 个答案:

答案 0 :(得分:0)

没有多余的空间?要走树,你需要一些堆栈......除非节点有父指针......所以让我们假设你可以使用一些堆栈。显然,如果您按升序排列值,则可以找到总和为' k'的所有对。所以:将树移动到最小的树,构建一个显式堆栈 - 即递归。复制堆栈。现在你可以按升序从那里开始两次散步。


进一步考虑,假设我们运行有序遍历,在每个阶段我们都有一个值为l的值,以及一个反向有序遍历,当前值为r。在任何给定的点,我们都有s == l + r,我们已经考虑了l左侧和r右侧的所有内容。如果s < k,我们前进到下一个(更大)l,如果s > k我们退回到下一个(更小)r,如果s == k有一个答案。 (我想我们可以假设树中的所有值都是唯一的,但如果不是,我们可能必须考虑给定l的给定rk的几个实例。

实现这一目标的关键是正向扫描功能:

  int forw(node* root, int l, int r, int k)

首先搜索节点l,然后继续搜索l + r >= k

一个类似的功能正在向另一个方向移动。

这些可以通过每个显式堆栈非常有效地实现,这避免了必须首先递归到(重新)找到lr的树位置...并指出与递归函数方法相比,显式堆栈不使用额外内存 - 实际上,可能使用 less 堆栈: - )

此外,树位置的重新定位会使O(n)更糟糕 - 添加一些O(log(n)),每次重新启动前向和后向扫描时都会增加一个。 / p>

答案 1 :(得分:0)

理论上不可能使用常数空间并且在没有任何附加属性的情况下以常数通过。

假设有k对与目标总和相加。在最坏的情况下,k在O(n)中。例如,1,1,1,1,1,1,1,1,1,1,1。目标总和是2.

如果您只进行常数的传递,则需要记住(即使它是一种有效的表示)有关其他节点的信息,以枚举总和达到目标值的对。如果你只想使用常量空间(即,不能记住),那么你必须按n的顺序进行多次传递(每次传递可能是次线性的),以枚举所有总和达到目标值的对。我看不到任何绕过它。

如果没有重复项,则在o(n log n)中执行它而不使用额外的内存是微不足道的。由于它是一个完整的二叉树,你可以有效地将它表示为一个数组(2i + 1 - 左子,2i + 2 - 右子,i / 2-父)。所以你得到了免费的父指针。但在这种情况下,n long n中不需要此属性。

即使您对元素进行排序,也要超过线性时间复杂度限制。