Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何在完全二叉树的最后一级找到最右节点的位置?_Algorithm_Binary Tree - Fatal编程技术网

Algorithm 如何在完全二叉树的最后一级找到最右节点的位置?

Algorithm 如何在完全二叉树的最后一级找到最右节点的位置?,algorithm,binary-tree,Algorithm,Binary Tree,我在二叉树中做一个问题,当我遇到一个问题,在一个完整的二叉树的最后一级找到最右边的节点,这里的问题是我们必须在O(n)时间内完成它,这是一个停止点,在O(n)中完成它很简单,通过遍历所有元素,但是有没有一种方法可以在小于O(n)的复杂度下完成这项工作,我在网上浏览了很多次,但我找不到关于这件事的任何信息。 提前感谢。因为它是一个完整的二叉树,所以遍历所有正确的节点,直到到达叶子为止,将取O(logN),而不是O(N)。在常规二叉树中需要O(N),因为在最坏的情况下,所有节点都排列在右侧,但由于它

我在二叉树中做一个问题,当我遇到一个问题,在一个完整的二叉树的最后一级找到最右边的节点,这里的问题是我们必须在O(n)时间内完成它,这是一个停止点,在O(n)中完成它很简单,通过遍历所有元素,但是有没有一种方法可以在小于O(n)的复杂度下完成这项工作,我在网上浏览了很多次,但我找不到关于这件事的任何信息。
提前感谢。

因为它是一个完整的二叉树,所以遍历所有正确的节点,直到到达叶子为止,将取O(logN),而不是O(N)。在常规二叉树中需要O(N),因为在最坏的情况下,所有节点都排列在右侧,但由于它是一个完整的二叉树,它不可能是

是的,您可以在
O(log(N)^2)
中通过执行二进制搜索的变体来完成

这可以通过先到最左边的元素1,然后到第二个最左边的元素,然后到第四个最左边的元素,第八,。。。直到你发现没有这样的元素。 假设您找到的最后一个元素是
i
th,第一个未找到的元素是
2i

现在,您只需在该范围内进行二进制搜索

这是
O(log(n/2))=O(logn)
总迭代次数,由于每次迭代都沿着整棵树进行,所以它是
O(log(n)^2)
时间的总和



(1) 在这里和下面的内容中,“x最左边的元素”仅指树最深处的节点。

我假设您知道节点的数量。让
n
这样的数字

在一个完整的二叉树中,级别
i
的节点数是级别
i-1
的两倍

因此,您可以在
2
之间迭代划分
n
。如果有剩余项,则
n
是正确的子项;否则,他就是一个左撇子。无论是否有余数,都要存储到序列中,最好是堆栈中

例如:

Stack<char> s;
while (n > 1)
{
  if (n % 2 == 0)
    s.push('L');
  else
    s.push('R');
  n = n/2; // n would int so division is floor
}
stacks;
而(n>1)
{
如果(n%2==0)
s、 推动('L');
其他的
s、 推动('R');
n=n/2;//n将为int,因此除法为floor
}
while
完成时,堆栈包含指向最右侧节点的路径


执行
时执行
的次数为
log_2(n)

这是具有时间复杂度O(lg n*lg n)和空间复杂度O(lg n)(考虑堆栈存储空间)的递归解决方案
使用下面代码的迭代版本,可以将空间复杂度降低到O(1)

    // helper function
    int getLeftHeight(TreeNode * node) {
      int c = 0;
      while (node) {
        c++;
        node = node -> left;
      }
      return c;
    }
    
    int getRightMostElement(TreeNode * node) {
      int h = getLeftHeight(node);

      // base case will reach when RightMostElement which is our ans is found
      if (h == 1)
        return node -> val;

      // ans lies in rightsubtree
      else if ((h - 1) == getLeftHeight(node -> right))
        return getRightMostElement(node -> right);

      // ans lies in left subtree
      else getRightMostElement(node -> left);
    }
时间复杂度推导- 在每个递归步骤中,我们考虑左子树或右子树,即最大高度(lgn)函数调用的n/2个元素,
计算高度需要花费lgn时间-

T(n) = T(n/2) + c1 lgn
   = T(n/4) + c1 lgn + c2 (lgn - 1)
   = ...
   = T(1) + c [lgn + (lgn-1) + (lgn-2) + ... + 1]
   = O(lgn*lgn)   

想想托马斯,我是说它会访问所有节点,我是在要求一个更好的方法,就像amit说的那样,如果你保存(并保持同步)树中的总节点数,那么它是O(logN),因为你知道什么时候访问左分支或右分支。将它添加到堆栈本身会导致O(n)时间,所以这一次并不重要,不是阿斯温·梅西利。插入堆栈是O(1)。请注意,还可以使用列表或向量。时间与插入次数绑定,即
log_2(n)