java - 在 O(logn) 中打印二叉树中的随机元素

标签 java algorithm random binary-tree

给定一个带有 TreeNode 的二叉树,如下所示:

class TreeNode {
    int data;
    TreeNode left;
    TreeNode right;
    int size;
}

其中size是(左子树+右子树+1)中的节点数。

Print a random element from the tree in O(logn) running time.

注意:这篇文章不同于this第一,正如明确提到的那样,我们有一个与此问题中的每个节点关联的 size

PS:写这篇文章的灵感来自 this .

最佳答案

有一种简单的方法可以提供 O(n) 的复杂度。

  • 生成一个范围在 1 到 root.size 之间的随机数
  • 做一个BFSDFS遍历
  • random numbered 处停止迭代元素并打印出来。

为了提高复杂性,我们需要在每次迭代时创建自己的分支顺序,而不是像 BFS 和 DFS 中那样按顺序进行。我们可以使用 size每个节点的属性决定是遍历左子树还是右子树。以下是方法:

  • 生成一个范围在 1 到 root.size 之间的随机数(说 r )
  • 从根节点开始遍历,决定是去左子树、右子树还是打印根:
    • 如果r <= root.left.size , 遍历左子树
    • 如果r == root.left.size + 1 , 打印根(我们已经找到要打印的随机节点)
    • 如果r > root.left.size + 1 ,遍历右子树
  • 本质上,我们定义了一个顺序,其中当前节点的排序为(当前节点的左子树的大小)+ 1。
  • 由于我们消除了在每次迭代时遍历左子树或右子树,因此其运行时间为 O(logn)。

伪代码看起来像这样:

traverse(root, random)
  if r == root.left.size + 1
    print root        
  else if r > root.left.size + 1
    traverse(root.right, random - root.left.size - 1)
  else
    traverse(root.left, random)

Java实现如下:

public static void printRandom(TreeNode n, int randomNum) {
    int leftSize = n.left == null ? 0 : n.left.size;
    if (randomNum == leftSize + 1)
        System.out.println(n.data);
    else if (randomNum > leftSize + 1)
        printRandom(n.right, randomNum - (leftSize + 1));
    else
        printRandom(n.left, randomNum);
}

关于java - 在 O(logn) 中打印二叉树中的随机元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34714479/

相关文章:

java - 在 querydsl 中调用 mysql 嵌套/内部函数

java - 更改 KeyPress 上 JTextField 的大小

algorithm - 在在线国际象棋游戏中,如何最大程度地减少时间控制滞后的影响?

java - Java 8 Stream.sum() 的错误行为

algorithm - 将一个链表拆分成3个链表

java - 为什么将 Random 与硬编码种子一起使用总是会产生相同的结果?

java - Map/Reduce wall-time 对 Reduce 任务的数量不敏感

java - 传递两个字符串数组并计算Java中x数组中y数组的出现次数

math - 来自 32 位自动递增 INTEGER 的伪随机数

java - math.random() 遵循哪些算法