Рубрики
Без рубрики

Как эффективно генерировать случайное подмножество?

Предположим, у вас есть массив с n элементами, и вы хотите случайное подмножество с элементами k. Какие стратегии могут вы думать о том, чтобы сделать это как можно эффективно? Найти минутку. Почему вы должны заботиться …

Автор оригинала: Alex Williams.

Предположим, у вас есть массив с n элементами, и вы хотите случайное подмножество с элементами k. Какие стратегии могут вы думать о том, чтобы сделать это как можно эффективно?

Найти минутку.

Почему вы должны заботиться о эффективности? Это потому, что генераторы случайных чисел должны сделать компромисс между статистическими тестами, которые они могут пройти и их производительность.

Займет другой момент.

Подсказка: Вы можете перевести это в проблему генерации случайных чисел от 0 до N – 1 без дубликатов? Эти цифры могут служить индексами, которые вы используете для выбора членов массива.

Что теперь? Кажется ли ваше решение слишком много работы, когда k маленький? Или это невозможно, когда K находится рядом? Здесь это ссылка, где она обсуждается. Если ваше решение имеет одну из упомянутых проблем, не чувствуй себя плохой Джон Скелет Дали 3 решения, ни один из которых не эффективны в целом.

Одно интересное решение состоит в том, чтобы объединить свои первые и второе подходы, то есть продолжайте собирать случайные числа и помещать их в хеш-набор или бинарное дерево, когда k маленький и перемешивает массив [0, …, n – 1], когда k большой Отказ Но что значит маленький и большой?

Для длинной истории вы можете посмотреть Screencast где я получу ответ. КОРОТКАЯ ВЕРСИЯ Я могу задать вопрос «Насколько большой CAN C будет до ожидаемого количества случайных чисел, которые необходимо превышать n»? Причина, по которой актуален этот вопрос, так это то, что подход 2 всегда требует случайных чисел. Оказывается красивый ответ; K <(1 -.63212055882 * N Если и только если ожидаемое количество случайных чисел, требуется

TL; DR Вот реализация в Python:

from random import randrange
def shuffle(list):
    n = len(list)
    for i in range(n - 1):
        j = randrange(i, n-1) # i <= j < n
        value = list[i]
        list[i] = list[j]
        list[j] = value
def getDistinctRandomNumbers(inclusiveMin, exclusiveMax, amount):
    result = set()
    while len(result) != amount:
        result.add(randrange(inclusiveMin, exclusiveMax))
    return result
def getRandomElements(list, amount):
    length = len(list)
    amount = min(length, amount)
    if amount < 0.63212055882 * length:
        randomNumbers = getDistinctRandomNumbers(0, length, amount)
        result = [None]*amount
        i = 0
        for num in randomNumbers:
            result[i] = list[num]
            i+=1
        return result
    else:
        shuffle(list)
        return list[0:amount]