【问题标题】:Binary Tree. Identify element v in T such that k-1 elements in T are smaller than v二叉树。识别 T 中的元素 v,使得 T 中的 k-1 个元素小于 v
【发布时间】:2013-09-28 01:10:48
【问题描述】:

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

给定二叉树 T 和一个不大于 T 中节点数的正整数 k,编写识别 T 中的元素 v 的伪代码,使得 T 中的 k-1 个元素恰好小于 v。你的代码应该花费时间最多与 T 的高度。

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

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

【问题讨论】:

  • 仔细查看您拥有的树结构,以及它附带的保证。如果不遍历子树,你知道它有多大吗?左子树中的所有内容是否都小于或等于当前节点的值?价值观是否不同?你知道一些关于子树的高度而不探索它们吗? “T的高度”实际上与“log n”成正比吗?
  • 我应该提到每个节点都包含一个元素大小,即以该节点为根的节点数。所以我可以通过查看它的 size 元素来知道一个子树有多大。并且左侧树中的所有内容都将小于当前节点的值。大小值并不总是不同的。可以有多个大小为 k-1 的节点。据我在课堂上学到的知识,树的高度总是与 log n 成正比。
  • 在节点v向右移动时,需要将搜索值调整为k - (1 + size of left child tree of v)。除此之外,您可以在 O(tree height) 中进行下降,因为您可以使用该大小计数器在每个节点上做出正确的决定。
  • 您能详细说明一下吗?我还是不明白。我仍然觉得它需要回到树上并检查右子树是否有左树大小为 k-1 的元素。假设我一直沿着左子树向下工作,检查每个左子树,直到到达空链接。我不应该检查右子树是否有左子树为 k-1 的元素吗?

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


【解决方案1】:

(我假设这棵树实际上是一个二叉搜索树,而不仅仅是任何旧的二叉树)

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

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

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

【讨论】:

  • The correct algorithm 看起来与问题中描述的相似,但问题确实是 O(n),而不是 O(d)。
【解决方案2】:

如果我们谈论的是常规二叉树,很容易证明您需要探索整个树才能找到这样的节点,所以我假设我们谈论的是二叉搜索树。

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

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

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

    A、X、Y 和 Z 都小于 N。(根据同样的规则,B 也小于 N)。

  • 节点N的左子节点

我怀疑你只是假设所有孩子都更小。

**剧透警告**

算法:

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

  1. 从顶部开始。

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

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

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

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

由于您只能向左或向右,并且节点数是恒定的(因为它是在节点级别上给出的),因此运行时间是 O(h) 其中 h 是树的高度,即 @987654330 @ 在平衡树中。

【讨论】:

    【解决方案3】:

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

    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)
    

    问题中没有直接给出 size(T) 为 O(1)(但 在 cmets 中澄清)。

    这最多需要 height(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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      相关资源
      最近更新 更多