如何使用每个节点的大小来查找O(h)

时间:2019-04-02 13:18:42

标签: java recursion binary-search-tree

给定k_1和k_2,在O(h)中找到BST k_1> = k <= k_2的范围

当h为高度且n为节点数时,我尝试使用O(h + n)编写代码。

Algorithm countRange(Node root, int k1, int k2) 
{
   if(root = null) return 0;
   if(root.value >= k1 && root.value <= k2) 
      return 1 + countRange(root.left, k1, k2) + countRange(root.right,k1,k2);
   else if(root.value < low)
      return countRange(root.right, k1, k2);
   else
      return countRange(root.left, k1, k2);

例如:

a[] = [1,2,3,4,5,6,7,8,9,10]以数组形式

countRange(4,8) = 5; // 4,5,6,7,8

如果有任何办法我们可以在O(h)次内完成该任务>作业中给出的提示是使用每个节点的大小,这是每个节点具有的后代节点。

例如

     8    <- size is 7

  6     10 <- size is 3

4   7  9   18  <- size is 1

1 个答案:

答案 0 :(得分:0)

一个主意:

  • 假设k1
  • 从根开始走树。对于某些节点(可能为零),您将同时拥有k1 node.value和k2> node.value,并选择右侧路径);
  • 请注意第一个不再存在的节点,因此路径会有所不同。假设此节点为D,则k1 D.value(由于k1 = k1的节点;从D向右遍历以搜索k2并计数值<= k2的节点。将总数加1(代表D)。
  • 当我说值> = k1的节点时,这并不意味着仅访问了节点。这是每个节点的后代计数起作用的地方:每次到达值> k1的节点时,因此您都需要左移以达到k1,还要计算该节点的所有右后代,因为所有他们将> k1。包括k1节点本身。
  • 在k2一侧,行为是对称的:当您获得一个右数时,计算所有的左后代节点,包括k2。
  • 这两个遍历都是O(h),因此总体也是O(h)。
  

         20
        /  \
       10   21
      / \    \
     /   \    \
    2     17  22
   / \     \
  1   6     19             
 /   / \    /
0   4   7  18
   / \
  3   5

让我们在该树中搜索[4,18]。

  • 从20开始,两个键都在左侧,因此忽略此节点。
  • 10点到达-这是D分开的地方。
  • 从10向4计数的左数> = 4,因此不计算2:4有1个右后代(5),6有1个右后代(7),总计4。
  • 从10计数到18右移<= 18,因此不计算19; 18和17都具有零个左侧后代,因此结果为2。
  • 总共有4 + 2 + 1 = 7:[4、5、6、7、10、17、18]