В предположении, что числа меньше единицы недопустимы и отсутствуют дубликаты, для этого существует простая процедура суммирования - сумма чисел от 1 до m с приращениями 1 равна (m * (m + 1)) / 2. Затем вы можете суммировать массив и использовать этот идентификатор.
Вы можете узнать, есть ли обман по вышеуказанным гарантиям, плюс гарантия, что номер не превышает m или меньше n (что можно проверить в O(N))
Идея в псевдокоде:
0) Начать с N = 0
1) Возьмите N-й элемент в списке.
2) Если он не в нужном месте, если список был отсортировано, проверьте, где он должен быть.
3) Если место, где оно должно быть, уже имеет тот же номер, у вас есть обман - ВОЗВРАЩАЕТСЯ ИСТИНА
4) В противном случае поменяйте местами числа (чтобы поместить первое число в в нужном месте).
5) С номером, который вы только что поменяли местами, он в нужном месте?
6) Если нет, вернитесь к шагу 2.
7) В противном случае начните с шага 1 с N = N + 1. Если это будет за концом списка, у вас нет дубликатов.
И да, это работает в O(N), хотя может выглядеть O(N ^ 2)
Всем на заметку (материал собран из комментариев)
Это решение работает в предположении, что вы можете изменить массив, а затем использует сортировку Radix на месте (что обеспечивает скорость O(N)).
Были предложены и другие математические решения, но я не уверен, что какое-либо из них было доказано. Существует множество сумм, которые могут быть полезны, но большинство из них приводит к чрезмерному увеличению количества битов, необходимых для представления суммы, что нарушает постоянную гарантию дополнительного пространства. Я также не знаю, способен ли какой-либо из них дать отличное число для данного набора чисел. Я думаю, что может работать сумма квадратов, для вычисления которой используется известная формула (см. Wolfram's)
Новое понимание (ну, больше размышлений, которые не помогают решить эту проблему, но интересны, и я иду спать):
Итак, было упомянуто, что можно использовать сумму + сумма квадратов. Никто не знал, сработало это или нет, и я понял, что это становится проблемой только тогда, когда (x + y) = (n + m), например, факт 2 + 2 = 1 + 3. Квадраты также имеют эту проблему благодаря троек Пифагора (поэтому 3 ^ 2 + 4 ^ 2 + 25 ^ 2 == 5 ^ 2 + 7 ^ 2 + 24 ^ 2, и сумма квадратов не работает). Если мы воспользуемся последней теоремой Ферма, мы знаем, что этого не может произойти для n ^ 3. Но мы также не знаем, нет ли для этого x + y + z = n (если только мы этого не сделаем, а я этого не знаю). Так что нет гарантии, что это тоже не сломается - и если мы продолжим идти по этому пути, у нас быстро закончатся биты.
Однако, обрадовавшись, я забыл отметить, что вы можете разбить сумму квадратов, но при этом вы создадите нормальную сумму, которая недействительна. Я не думаю, что вы можете сделать и то, и другое, но, как уже отмечалось, в любом случае у нас нет доказательств.
Я должен сказать, что найти контрпримеры иногда намного проще, чем что-то доказывать! Рассмотрим следующие последовательности, каждая из которых имеет сумму 28 и сумму квадратов 140:
[1, 2, 3, 4, 5, 6, 7]
[1, 1, 4, 5, 5, 6, 6]
[2, 2, 3, 3, 4, 7, 7]
Таких примеров длиной 6 и меньше я найти не смог. Если вам нужен пример с правильными минимальными и максимальными значениями, попробуйте этот длиной 8:
[1, 3, 3, 4, 4, 5, 8, 8]
Более простой подход (изменение идеи Хаззена):
Целочисленный массив длины m содержит все числа от n до n + m-1 ровно один раз, если и только если
- каждый элемент массива находится между n и n + m-1
- нет дубликатов
(Причина: в данном целочисленном диапазоне есть только m значений, поэтому, если массив содержит m уникальных значений в этом диапазоне, он должен содержать каждое из них один раз)
Если вам разрешено изменять массив, вы можете проверить оба за один проход по списку с модифицированной версией идеи алгоритма Хаззена (нет необходимости производить какое-либо суммирование):
- For all array indexes i from 0 to m-1 do
- If array[i] < n or array[i] >= n+m => RETURN FALSE ("value out of range found")
- Вычислить j = array [i] - n (отсчитываемая от 0 позиция array [i] в отсортированном массиве со значениями от n до n + m-1)
- While j is not equal to i
- If list[i] is equal to list[j] => RETURN FALSE ("duplicate found")
- Поменять местами список [i] на список [j]
- Пересчитать j = array [i] - n
- ВОЗВРАТ ИСТИНА
Я не уверен, учитывается ли модификация исходного массива максимально допустимым дополнительным пространством O (1), но если это не так, это должно быть решение, которое хотел исходный плакат.
person
Community
schedule
07.10.2008
O(m) (single pass) and O(1) in spaceне имеет контрпримеров - алгоритм uniqueSet stackoverflow.com/questions/177118/ - person jfs   schedule 09.10.2008int m) stackoverflow.com/questions/177118/# 311497 - person jfs   schedule 22.11.2008nвходным параметром задачи. - person AnT   schedule 06.11.2009