Предположим, у нас есть массив с целыми числами от -N до N в массиве размером 2N + 1. Сначала мы перемешиваем элементы в массиве, затем пытаемся найти максимальное целое число, перебирая массив от первого элемента до последнего элемента: (пример кода на Java)
int called = 0;
int max = Integer.MIN_VALUE;
for (int i : array) {
if (i > max) {
called++;
max = i;
}
}
Каково ожидание (среднее за многие прогоны) значения called
после итерации по массиву?
Редактировать:
Как я обнаружил, что это близко к ln (array.length):
public static void main(String args[]) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 1000000; i++) list.add(i);
int called = 0;
int runs = 100;
for (int i = 1; i <= runs; i++) {
Collections.shuffle(list);
int max = -1;
for (int num : list) {
if (num > max) {
called++;
max = num;
}
}
}
System.out.println("Expectation: " + called/runs);
}
2 ответа
Рассмотрим случайно перемешанный массив. Мы хотим оценить K - во сколько раз i-й элемент больше всех своих предшественников.
Ожидаемое значение K равно сумме вероятностей того, что i-й элемент больше всех своих предшественников. E (K) = Σ 1 2N + 1 P i .
Теперь мы хотим найти P i . Рассмотрим префикс длины i для нашего массива. Вероятность того, что последний элемент префикса будет самым большим, равна 1 / i. Итак, мы имеем P i = 1 / i.
Следовательно: E (K) = Σ 1 2N + 1 1 / i. Мы можем оценить эту сумму через определенный интеграл как ln (2N + 1) + O (1).
Итак, ответ - ln (2N + 1) + O (1).
И моделирование Монте-Карло в качестве доказательства:
constexpr size_t N = 1000;
std::array<int, 2 * N + 1> arr;
std::iota(arr.begin(), arr.end(), -N);
std::random_device rd;
std::mt19937 g(rd());
double moving = 0;
for (double trial = 1; trial < 10001; ++trial) {
std::shuffle(arr.begin(), arr.end(), g);
int called = 0;
int max = std::numeric_limits<int>::min();
for (int i = 1; i < arr.size(); ++i) {
if (arr[i] > max) {
++called;
max = arr[i];
}
}
if (trial > 1) {
moving = moving * ((trial - 1) / trial) + called / trial;
}
else {
moving = called;
}
}
cout << "actual: " << moving << endl;
cout << "expected: " << std::log(2 * N + 1) << " + O(1)" << endl;
actual: 8.1581 expected: 7.6014 + O(1)
Первоначально я столкнулся с этой проблемой во время собеседования с программистом. Вот что я нашел, что можно использовать для решения этой проблемы:
Как указали Йола и Ричи, ответ должен быть ln (n) + γ (где γ - это константа Эйлера-Маскерони, а n - количество элементов в массиве).
Похожие вопросы
Новые вопросы
arrays
Массив - это упорядоченная линейная структура данных, состоящая из набора элементов (значений, переменных или ссылок), каждый из которых идентифицируется одним или несколькими индексами. Когда вы спрашиваете о конкретных вариантах массивов, используйте вместо них следующие связанные теги: [vector], [arraylist], [matrix]. При использовании этого тега в вопросе, относящемся к языку программирования, пометьте вопрос используемым языком программирования.