N-е наименьшее число среди двух баз данных размером n, каждый из которых использует разделение и завоевание

У нас есть две базы данных размера n, содержащие числа без повторов. Итак, всего у нас 2n элементов. Они могут быть доступны через запрос к одной базе данных одновременно. Запрос таков, что вы даете ему ak, и он возвращает kth наименьшую запись в этой базе данных. Нам нужно найти n-ю наименьшую запись среди всех 2n элементов в O (log n) запросах.

Идея состоит в том, чтобы использовать разделяй и властвуй, но мне нужна помощь, чтобы обдумать это. Спасибо!

Ответ 1

Вот как я это продумал. Поскольку это образовательная проблема, я предлагаю вам прекратить читать, если какой-либо из соображений заставляет вас думать: "Ага, я не думал об этом, я могу думать дальше по этим строкам".

1) Такое же наблюдение, как и sdcwc: с возможным небольшим поводом для того, начинается ли он с 0 или 1, базу данных можно рассматривать как отсортированный массив. Я прошу элемент 0, я получаю наименьшее количество. Я прошу 12, я получаю 13-е место. И так далее. Мне это легче понять.

2) Мы знаем, что мы ищем алгоритм O (log n). Это означает, что, грубо говоря, мы ищем одну из двух вещей:

  • Либо мы начинаем вычислять наименьший элемент, а затем вычисляем 2-й наименьший, 4-й наименьший, 8-й и т.д., пока мы не достигнем необходимого размера, каждый шаг в постоянное время. Это не кажется мне многообещающим.

  • Или мы начинаем с проблемы размера n, тогда мы выполняем некоторую операцию с постоянным временем, которая позволяет нам решить исходную задачу, решая проблему размера n/2. Очевидно, что мы можем решить задачу для n = 1 в постоянное время, чтобы завершить алгоритм. Это звучит немного правдоподобно.

На самом деле это необязательно должно быть n/2 каждый раз. Это может быть n/3, или 999 * n/1000, и результат будет по-прежнему равен O (log n). Но нет никакого вреда в поиске n/2 в первую очередь.

3) Как мы собираемся уменьшить проблему? Ну, если мы можем убрать/удалить m элементов с самого начала одного массива или меньше, чем на k-м наименьшем, тогда мы найдем (km) -ый наименьший элемент результирующей пары массивов, и это будет kth наименьший из исходных массивов.

4) Наконец, прорывное наблюдение состоит в том, что если m-й наименьший элемент массива A меньше, чем m-й наименьший элемент массива B, то этот m-й элемент из A не может быть (2m) -м наименьшим элементом двух массивы объединены. Он меньше этого (или равного значения: я не уверен, означает ли "нет повторов" означает "нет повторений в каждой базе данных" или "нет повторений между объединенными базами данных" ), поскольку не более 2 * (м- 1) элементы, строго меньшие, чем в обоих массивах, объединенные.

Если я сделал ошибку, остальное кодирование. С небольшим дополнительным аргументом для учета off-by-1, когда k нечетно, это решение на самом деле O (log k), которое является O (log n), так как k <= 2 * n.

Ответ 2

Я видел эту проблему на квалификационном экзамене недавно, и это пахнет проблемой домашних заданий. Поэтому я сделаю только два предложения:

  • Изучите бинарный поиск с уделением особого внимания точной природе инвариантов цикла. Книга Джона Бентли "Программирование жемчуга" имеет хорошее объяснение.

  • Попробуйте обобщить инварианты для двоичного поиска.

  • Нарисуйте картинку с различными специальными случаями:

    • Каждое число в DB1 меньше, чем каждое число в DB2
    • И наоборот
    • DB1 равно DB2
    • Каждый номер в DB2 в два раза превышает соответствующий номер в DB1

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

Ответ 3

Советов:

  • Соблюдайте свои "базы данных" - это действительно два отсортированных массива.
  • Возьмите элементы из "середины" массивов и сравните их. Результат сравнения может позволить вам "исключить" часть.