Это должно сработать, если вы имеете дело с целыми числами размера O(log n)
. Это Python реализация набросанного алгоритма @ גלעד רקן answer (включая комментарии @OneLyner), где медиана заменена средним или средним значением.
def mean(items):
result = 0
for i, item in enumerate(items, 1):
result = (result * (i - 1) + item) / i
return result
def midval(items):
min_val = max_val = items[0]
for item in items:
if item < min_val:
min_val = item
elif item > max_val:
max_val = item
return (max_val - min_val) / 2
def find_singleton(items, pivoting=mean):
n = len(items)
if n == 1:
return items[0]
else:
# find pivot - O(n)
pivot = pivoting(items)
# partition the items - O(n)
j = 0
for i, item in enumerate(items):
if item > pivot:
items[j], items[i] = items[i], items[j]
j += 1
# recursion on the partition with odd number of elements
if j % 2:
return find_singleton(items[:j])
else:
return find_singleton(items[j:])
Следующий код предназначен только для проверки работоспособности случайных входных данных:
def gen_input(n, randomize=True):
"""Generate inputs with unique pairs except one, with size (2 * n + 1)."""
items = sorted(set(random.randint(-n, n) for _ in range(n)))[:n]
singleton = items[-1]
items = items + items[:-1]
if randomize:
random.shuffle(items)
return items, singleton
items, singleton = gen_input(100)
print(singleton, len(items), items.index(singleton), items)
print(find_singleton(items, mean))
print(find_singleton(items, midval))
Для симметричного c распределения медиана и среднее или среднее значение совпадают. С помощью требования log (n) к количеству битов для записей можно показать, что любая произвольная подвыборка не может быть искажена настолько, чтобы обеспечить более log(n)
рекурсий.
Например, учитывая случай k = log (n) битов с k = 4 и только положительными числами, наихудший случай: [0, 1, 1, 2, 2, 4, 4, 8, 8, 16, 16]
. Здесь поворот по среднему будет уменьшать ввод на 2 за раз, что приводит к k + 1 рекурсивным вызовам, но добавление любой другой пары ко входным данным не увеличит количество рекурсивных вызовов, но увеличит размер ввода.
(ОТредактировано для лучшего объяснения.)