Простой вопрос интервью усложнился: по номерам 1..100 найдите пропущенные числа, по которым точно k отсутствуют

Одна вещь о быстрой сортировке php (asort, arsort и т. д.) заключается в том, что они обменивают ваши равные значения, то есть значения с разными ключами будут случайным образом менять позицию даже между разными прогонами. Удивительно, что код может производить другой порядок, используя одни и те же данные снова и снова. В конце концов, мне пришлось реализовать свой собственный быстрый вид, чтобы удалить эту аномалию.

1092
задан smci 28 April 2019 в 01:04
поделиться

11 ответов

Вот краткое содержание ссылки Димитриса Андреу.

Вспомните сумму i-й степени, где i=1,2,...,k. Это сводит задачу к решению системы уравнений

a1 + a2 + ... + ak = b1

a12 + a22 + ... + ak2 = b2

...

a1k + a2k + ... + akk = bk

Используя тождества Ньютона, зная bi, можно вычислить

c1 = a1 + a2 + ... ... ak

c2 = a1a2 + a1a3 + ... + ak-1ak

...

ck = a1a2 ... ak

Если разложить многочлен (x-a1) ... (x-ak), то коэффициенты будут в точности c1, ..., ck - см. формулы Виета. Так как каждый многочлен уникально коэффициентирует (кольцо многочленов является евклидовой областью), это означает, что ai уникально определены, вплоть до перестановки.

На этом доказательство того, что для восстановления чисел достаточно вспомнить силы, заканчивается. Для постоянного k это хороший подход.

Однако, когда k меняется, прямой подход вычисления c1,...,ck является запредельно дорогим, так как, например, ck является произведением всех недостающих чисел, величиной n!/(n-k)! Чтобы преодолеть это, проводите вычисления в поле Zq, где q - простое число, такое, что n <= q < 2n - оно существует по постулату Бертрана. Доказательство не нужно менять, так как формулы остаются верными, а факторизация многочленов по-прежнему уникальна. Также необходим алгоритм факторизации над конечными полями, например, алгоритм Берлекампа или Кантора-Зассенхауса.

Псевдокод высокого уровня для константы k:

  • Вычислите i-ые степени заданных чисел
  • Вычтите, чтобы получить суммы i-ых степеней неизвестных чисел. Назовите суммы bi.
  • Используя тождества Ньютона, вычислите коэффициенты от bi; назовите их ci. В основном, c1 = b1; c2 = (c1b1 - b2)/2; точные формулы см. в Википедии
  • Коэффициент многочлена xk-c1xk-1 + ... .. + ck.
  • Корнями многочлена являются нужные числа a1, ..., ak.

Для переменного k найдите простое число n <= q < 2n, используя, например, метод Миллера-Рабина, и проделайте шаги со всеми числами, уменьшенными по модулю q.

EDIT: В предыдущей версии этого ответа говорилось, что вместо Zq, где q - простое, можно использовать конечное поле характеристики 2 (q=2^(log n)). Это не так, поскольку формулы Ньютона требуют деления на числа до k.

.
579
ответ дан 19 December 2019 в 20:16
поделиться

Вы найдете его, прочитав пару страниц книги Muthukrishnan - Data Stream Algorithms: Puzzle 1: Finding Missing Numbers . Он показывает именно то обобщение, которое вы ищете . Вероятно, это то, что прочитал ваш интервьюер и почему он задал эти вопросы.

Теперь, если бы только люди начали удалять ответы, которые относятся или заменяются трактовкой Мутукришнана, и облегчили бы поиск этого текста. :)


Также см. sdcvvc напрямую связанный ответ , который также включает псевдокод (ура! Не нужно читать эти сложные математические формулировки :)) (спасибо, отличная работа!).

237
ответ дан 19 December 2019 в 20:16
поделиться

Мы можем решить Q2, сложив как сами числа, так и квадратов чисел.

Затем мы можем свести проблему к

k1 + k2 = x
k1^2 + k2^2 = y

, где x и y - насколько суммы ниже ожидаемых значений.

Подстановка дает нам:

(x-k2)^2 + k2^2 = y

Что мы затем можем решить, чтобы определить наши недостающие числа.

171
ответ дан 19 December 2019 в 20:16
поделиться

Не уверен, что это наиболее эффективное решение, но я бы перебрал все записи и использовал битовый набор, чтобы запомнить, какие числа установлены, а затем проверить на 0 бит.

Мне нравятся простые решения - и я даже считаю, что они могут быть быстрее, чем вычисление суммы или суммы квадратов и т. Д.

34
ответ дан 19 December 2019 в 20:16
поделиться

Я не проверял математику, но подозреваю, что вычисление Σ (n ^ 2) в том же проходе, что и вычисление Σ (n) , предоставит достаточно информации для получить два пропущенных числа, Do Σ (n ^ 3) также, если их три, и так далее.

32
ответ дан 19 December 2019 в 20:16
поделиться

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

Если мы обобщим решение для чисел от 1 до N, ничего не изменится, за исключением того, что N не является константой, поэтому мы находимся в O (N - k) = O (N) времени. Например, если мы используем набор битов, мы устанавливаем биты в 1 за O (N) раз, перебираем числа, устанавливая биты в 0 по мере продвижения (O (Nk) = O (N)), а затем мы есть ответ.

Мне кажется, что интервьюер спрашивал вас, как распечатать содержимое окончательного набора за время O (k), а не за время O (N). Ясно, что с установленным битом вам нужно перебрать все N бит, чтобы определить, следует ли вам печатать число или нет. Однако, если вы измените способ реализации набора, вы можете распечатать числа за k итераций. Это делается путем помещения чисел в объект, который будет храниться как в хэш-наборе, так и в двусвязном списке. Когда вы удаляете объект из хеш-набора, вы также удаляете его из списка. Ответы останутся в списке длины k.

13
ответ дан 19 December 2019 в 20:16
поделиться

Вы можете проверить, все ли числа существуют? Если да, вы можете попробовать следующее:

S = сумма всех чисел в сумке (S <5050)
Z = сумма пропущенных чисел 5050 - S

, если пропущенные числа x и y , то:

x = Z - y и
max (x) = Z - 1

Итак, вы проверяете диапазон от 1 до max (x) и находите число

5
ответ дан 19 December 2019 в 20:16
поделиться

Очень хорошая задача. Я бы пошел на использование заданной разницы для Qk. Многие языки программирования даже поддерживают его, например, в Ruby:

missing = (1..100).to_a - bag

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

1
ответ дан 19 December 2019 в 20:16
поделиться

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

Итак, поскольку вы видите все числа, просто найдите пропущенное число. То же самое происходит, когда отсутствуют два числа. Думаю, довольно просто. Нет смысла использовать уравнение, когда вы видите числа, оставшиеся в сумке.

0
ответ дан 19 December 2019 в 20:16
поделиться

Для разных значений k подход будет другим, поэтому универсального ответа в терминах k не будет. Например, для k = 1 можно воспользоваться суммой натуральных чисел, но для k = n / 2 нужно использовать какой-то битовый набор. Таким же образом для k = n-1 можно просто сравнить единственное число в сумке с остальными.

-4
ответ дан 19 December 2019 в 20:16
поделиться

Попробуйте найти произведение чисел от 1 до 50:

Пусть произведение, P1 = 1 x 2 x 3 x ............. 50

Когда вы вынимаете числа одно за другим, умножайте их так, чтобы получилось произведение P2. Но здесь отсутствуют два числа, следовательно, P2 < P1.

Произведение двух ошибочных терминов, a x b = P1 - P2.

Вы уже знаете сумму, a + b = S1.

Из двух приведенных выше уравнений решайте для a и b через квадратное уравнение. a и b - ваши недостающие номера.

-1
ответ дан 19 December 2019 в 20:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: