二进制搜索树(BST)中的数字添加到某个值

时间:2010-10-13 16:25:01

标签: algorithm binary-tree

给定一个BST,是否有可能找到两个加起来给定值的数字,在O(n)时间和额外的内存很少。通过少量额外内存,暗示您无法将整个BST复制到数组中。

3 个答案:

答案 0 :(得分:4)

如果你有子指针和父指针,这可以在O(n)时间和O(1)额外内存中完成。保留两个指针x和y,并在最小元素处开始x,在最大元素处开始y。如果这两个元素的总和太低,则将x移动到其后继,如果它太高则将y移动到其前一个元素。一旦x指向比y更大的元素,就可以报告失败。对于总共O(n)个边缘遍历,树中的每个边最多遍历两次,并且您唯一的内存使用是两个指针。如果没有父指针,你需要记住根的祖先序列,至少是Omega(log n),如果树是不平衡的,可能更高。

要查找后继者,您可以使用以下伪代码(前一代表的类似代码):

succ(x) {
  if (x.right != null) {
    ret = x.right;
    while (ret.left != null) ret = ret.left;
    return ret;
  } else {
    retc = x;
    while (retc.parent != null && retc.parent < x) retc = retc.parent;
    if (retc.parent != null && retc.parent > x) return retc.parent;
    else return null;
  }
}

答案 1 :(得分:2)

我认为jonderry非常接近,但是父指针需要\ Omega(n)内存,即它们大大增加了内存使用量。他正在做的是在相反的方向上进行两次协调遍历(从小到大和viveversa),试图保持总和始终接近目标,你可以用两个堆栈来管理它,并且堆栈只能长到树的深度那就是O(log n)。我不知道这是否是“小”的额外内存,但肯定是额外的内存和o(n)。所以这与jonderry自己的注释完全一样,但是没有运行时惩罚,因为仅使用堆栈遍历二叉树是众所周知且高效且绝对是O(n)操作。所以你有增加迭代器ii和减少迭代器di。

x = ii.next()
y = di.next()
while (true) {
  try:
    if x + y > target {y = di.next()}
    if x + y < target {x = ii.next()}
    if x + y == target {return (x,y)}
  except IterError:
    break
}
return None

我在计算假媒体的上下文中遇到了同样的问题,即样本中所有成对平均值的中位数。

答案 2 :(得分:-1)

是的,如果你解析它,因为它将是一个排序数组。