Can I choose a random element from a set if I don't know the size of the set?

点点圈 提交于 2019-12-06 03:06:46

Start with max_r = -1 and rand_node = null. Iterate through the tree. For each node meeting the criteria:

r = random()
if r > max_r:
  rand_node = node
  max_r = r

At the end rand_node will be a randomly selected node with only a single iteration required.

You can do this without first creating a list (sorry for my C pseudo code)

int index = 0;
foreach (element)
{
    if (element matches criteria)
    {
        index++;
        int rand = random value in [1 index] range
        if (1 == rand)
        {
            chosen = element;
        }
    }
}

The math works out, say you have a list where 3 of the elements match the criteria, the probability that the first element will be chosen is:

1 * (1 - 1 / 2) * (1 - 1 / 3) = 1 * (1 / 2) * (2 / 3) = 1 / 3

The probability of the second being chose is:

(1 / 2) * (1 - 1 / 3) = (1 / 2) * (2 / 3) = 1 / 3

and finally for the third element

1 / 3

Which is the correct answer.

You could recursively do this:

  1. Traverse the current tree level, creating a list
  2. Select a random node from it (using a random number from 0 to list.Length)
  3. Repeat until you get to a leaf node

that would give items in small subtrees a higher probability of being selected though.

Alternatively, you don't need to build a list, you only need to keep track of the number of items. That would mean traversing the tree a second time to get to the selected item, but you wouldn't need the extra memory for the list.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!