二叉树。识别T中的元素v,使得T中的k-1个元素小于v

时间:2013-09-28 01:10:49

标签: algorithm binary-tree binary-search-tree

我有这个问题需要解决。我不是在寻找答案,而是在寻找应该去的地方。我有一个算法,但它不是O(log n)。

给定二叉树T和一个不大于T中节点数的正整数k,写入伪代码来识别T中的元素v,使得T中的精确k - 1个元素小于v。您的代码应该花时间最多与之成正比 T的高度。

我在这里的基本想法是,我首先检查左侧树,检查左侧树的大小。如果左侧树的大小大于k-1,则继续向左搜索。否则我会搜索右。如果整个左侧树不包含具有k-1个元素的节点,则我搜索右侧子树。问题是我知道这不是O(log n),因为最坏的情况是我必须搜索树中的每个节点。

我有什么遗失的吗?任何提示或帮助都会很棒,但请不要只给我一个答案。

3 个答案:

答案 0 :(得分:0)

(我假设树实际上是二进制搜索树,而不仅仅是任何旧的二叉树)

您的算法为O(d),其中d是树的最大深度。

这是因为每次进行这种比较时,你会继续向下一级(假设你还没有找到该元素)。因此,您将最多进行与树中的级别一样多的比较。

因此,除非您的树真的不平衡,否则您实际上并不会查看每个元素。事实上,如果你可以假设树是平衡的,那么你已经很好了(为什么?)。

答案 1 :(得分:0)

如果我们谈论的是常规二叉树,那么很容易证明你需要探索整个树来找到这样一个节点,所以我假设我们正在谈论二元搜索树。

在二叉搜索树中,以下小于节点N:

  • 节点A,它的左子节点及其所有后代,其中节点B是节点A的右子节点,节点B是节点N或其任何祖先。

        A
       / \
      X   B
     /     \
    Y      ...
     \     /
      Z   N
    

    A,X,Y和Z都小于N.(按照同样的规则,B也小于N)。

  • 节点N的左子项

我怀疑你假设所有的孩子都比较小。

** SPOILER ALERT **

<强>算法:

寻找m元素较小的节点......

  1. 从顶部开始。

  2. x =左子树中的节点数(如果没有左子,则x = 0)

  3. 如果x = m,则返回当前节点。

  4. 如果x < m,请向左递归。

  5. 如果x > m,请设置m = m - x - 1并向右递送。

  6. 由于您只向左或向右移动,并且节点计数是常量(因为它是在节点级别给出的),因此运行时间为O(h),其中h是树的高度,在平衡树中是O(log n)

答案 2 :(得分:0)

它与quickselect的算法几乎相同。根据左分支的大小递归到左或右分支。

Find(T, k) :=
    size(T.left) == k - 1 -> return T
    size(T.left) > k - 1 -> return Find(T.left, k)
    size(T.left) < k - 1 -> return Find(T.right, k - size(T.left) - 1)

问题中没有直接给出(但 在评论中澄清)尺寸(T)是O(1)。

这需要最多高度(T)步长,因为在每个递归步骤中高度至少减少1。

你也可以迭代地写这个:

Find(T, k) := 
   while size(T.left) != k - 1:
       if size(T.left) > k - 1:
           T = T.left
       else:
           T = T.right
           k -= size(T.left) + 1
   return T