Обычно в алгоритмах мы не заботимся о сравнении, сложении или вычитании чисел - мы предполагаем, что они выполняются за время . Например, мы предполагаем это, когда говорим, что сортировка на основе сравнения - это O ( n log n ) , но когда числа слишком велики, чтобы поместиться в регистры, мы обычно представляем их как массивы, поэтому базовые операции требуют дополнительных вычислений для каждого элемента.
Есть ли доказательства, показывающие, что сравнение двух чисел (или других примитивных арифметических функций) может быть выполнено в ? Если нет, то почему мы говорим, что сортировка на основе сравнения - это O ( n log n ) ?
Я столкнулся с этой проблемой , когда я ответил так вопрос , и я понял , что мой алгоритм не , потому что рано или поздно я должен иметь дело с большим-ИНТ, и это не алгоритм псевдо полиномиальное время он был P .
Ответы:
Для таких людей, как я, которые изучают алгоритмы для жизни, стандартная модель вычислений 21-го века - это целочисленная RAM . Модель предназначена для более точного отражения поведения реальных компьютеров, чем модель машины Тьюринга. Реальные компьютеры обрабатывают многоразрядные целые числа в постоянное время, используя параллельное оборудование; не произвольные целые числа, но (поскольку размеры слов неуклонно растут с течением времени), а также целые числа фиксированного размера .
Модель зависит от одного параметра , называемого размером слова . Каждый адрес памяти содержит одно w- битное целое число или слово . В этой модели входной размер n - это количество слов на входе, а время выполнения алгоритма - это количество операций над словами . Стандартные арифметические операции (сложение, вычитание, умножение, целочисленное деление, остаток, сравнение) и логические операции (побитовое и, или, xor, сдвиг, вращение) над словами требуют O ( 1 ) времени по определению .w w n O(1)
Формально размер слова НЕ является константойw для анализа алгоритмов в этой модели. Чтобы привести модель в соответствие с интуицией, нам требуется , поскольку в противном случае мы даже не можем хранить целое число n в одном слове. Тем не менее, для большинства нечисловых алгоритмов время выполнения фактически не зависит от w , потому что эти алгоритмы не заботятся о базовом двоичном представлении их входных данных. И Mergesort, и Heapsort работают за O ( n log n ) ; медиана 3-х быстрой сортировки выполняется в O ( n 2w≥log2n n w O(nlogn) Время в худшем случае. Одним заметным исключением является двоичная радикальная сортировка, которая выполняется за время O ( n w ) .O(n2) O(nw)
Установка дает нам традиционную модель оперативной логарифмической стоимости. Но некоторые алгоритмы целочисленного ОЗУ предназначены для больших размеров слов, например алгоритм целочисленной сортировки по линейному времени, разработанный Andersson et al. , что требует w = Ω ( log 2 + ε n ) .w=Θ(logn) w=Ω(log2+εn)
Для многих алгоритмов, возникающих на практике, размер слова просто не является проблемой, и мы можем (и делаем) прибегнуть к гораздо более простой модели ОЗУ с одинаковой стоимостью. Единственная серьезная трудность связана с вложенным умножением, которое можно использовать для очень быстрого построения очень больших целых чисел . Если бы мы могли выполнять арифметику с произвольными целыми числами за постоянное время, мы могли бы решить любую проблему в PSPACE за полиномиальное время .w
Обновление: я должен также упомянуть, что есть исключения из «стандартной модели», такие как алгоритм целочисленного умножения Фюрера , который использует многолинейные машины Тьюринга (или, что эквивалентно, «битовая память»), и большинство геометрических алгоритмов, которые анализируются теоретически чистая, но идеализированная модель "реального ОЗУ" .
Да, это банка червей.
источник
источник
Чтобы ответить на поставленный вопрос: алгоритмисты просто делают это довольно часто, используя модель ОЗУ. Для сортировки во многих случаях люди даже анализируют более простую модель сравнения , о которой я немного подробнее расскажу в связанном ответе.
Чтобы ответить на неявный вопрос о том, почему они это делают: я бы сказал, что эта модель обладает довольно хорошей прогностической силой для некоторых типов комбинаторных алгоритмов, в которых все числа являются «маленькими» и на реальных машинах помещаются в регистры.
Чтобы ответить на неявное продолжение о численных алгоритмах: Нет, старая модель ОЗУ здесь не стандартная. Даже устранение Гаусса может потребовать некоторой осторожности. Как правило, для вычисления ранга вводится лемма Шварца (например, раздел 5 здесь ). Другим каноническим примером является анализ алгоритма эллипсоида, который требует некоторой осторожности для анализа.
И наконец: люди думали о сортировке строк раньше , даже недавно.
Обновление: проблема с этим вопросом заключается в том, что «мы» и «предположим» не так точно определены. Я бы сказал, что люди, которые работают в модели RAM, не занимаются численными алгоритмами или теорией сложности (где определение сложности деления было знаменитым результатом ).
источник
python -mtimeit "$a * $b"
$a
$b = 2*$a
источник
источник
Я бы сказал, что мы обычно принимаем O (1) арифметические операции, потому что мы обычно делаем вещи в контексте 32-битных целых или 64-битных целых чисел или чисел с плавающей запятой IEEE 754. O (1), вероятно, является довольно хорошим приближением для такого рода арифметики.
Но в целом это не так. В общем, вам нужен алгоритм для выполнения сложения, вычитания, умножения и деления. Вычислительность и логика Булоса, Берджесса и Джеффериса приходят на ум как способ понять доказательство (я) этого, с точки зрения пары различных формальных систем, рекурсивных функций и машин Abacus, по крайней мере, в моей копии 4-го издания.
Вы можете посмотреть на термины лямбда-исчисления для вычитания и деления с помощью церковных цифр, чтобы легко понять, почему эти две операции не являются O (1). Немного сложнее увидеть сложение, умножение и возведение в степень, но оно есть, если принять во внимание форму самих церковных цифр.
источник