我的一位朋友有以下面试问题,我们都不确定答案是什么。有没有人知道如何处理这个问题?
给定不平衡的二叉树,描述一种随机选择节点的算法,使每个节点具有相同的被选择概率。
答案 0 :(得分:5)
您可以通过树的一次传递来完成。该算法与列表相同。
当您看到树中的第一个项目时,将其设置为所选项目。
当你看到第二个项目时,你会选择一个范围内的随机数(0,2)。如果它是1,那么新项目将成为所选项目。否则你跳过该项目。
对于您看到的每个节点,您都会增加计数,并以1 / count的概率选择它。因此,在第101个节点,您可以选择范围内的随机数(0,101)。如果它是100,则该节点是新选择的节点。
完成遍历树后,返回选定的节点。该操作在时间上是O(n),其中n是树中的节点数,空间中是O(1)。无需预处理。
答案 1 :(得分:1)
我们可以通过在解析树和选择左右子树中的节点数时选择随机节点,在一个解析中递归地执行此操作。在递归的每一步,我们返回根节点的数量和从根节点的子树中的节点随机选择的随机节点。
假设左子树中的节点数是n_l,右子树中的节点数是n_r
。此外,从左侧和右侧子树中随机选择的节点分别为R_l
和R_r
。然后,在[0,1]中选择一个统一的随机数并选择概率为R_l
的{{1}}或选择概率为n_l/(n_l+n_r+1)
的根或选择1/(n_l+n_r+1)
概率R_r
}。
答案 2 :(得分:0)
如果您只进行一次查询,并且您还没有对每个节点进行计数,那么您可以获得的最佳时间复杂度为O(n)
,因此深度优先搜索方法将是最好的一个。
对于重复查询,最佳选择取决于给定的约束 (最快的每查询方法是使用补充数组)。
O(n)
空格,O(n)
预处理,O(1)
插入/移除,O(1)
查询
有一个包含所有节点的补充数组。
还要让每个节点都存储自己的索引(所以你可以在O(1)中将它从数组中删除 - 这样做的方法是将它与数组中的最后一个元素交换,更新节点的索引适当地在最后一个索引处并减小数组的大小(删除最后一个元素)。
要获得随机节点,只需在数组中生成随机索引。
修改后的树(O(n)
空间),N / A(或O(n)
)预处理,O(depth)
插入/移除,O(depth)
查询 < / p>
让每个节点包含其子树中的元素数。
生成随机节点时,根据生成的随机数的值以及左或右子树的计数向左或向右移动。
// note that subtreeCount = leftCount + rightCount + 1
val = getRandomNumber(subtreeCount)
if val = 0
return this node
else if val <= leftCount
go left
else
go right
O(depth)
空格,O(1)
预处理,O(1)
插入/移除,O(n)
查询
计算树中的节点数(如果您还没有计数)。
生成介于0和节点数之间的随机数。
只需在树中进行深度优先搜索,并在处理完所需数量的节点后停止。
这假设一个节点没有parent
成员 - 这将使O(1)
空间成为可能。