Обычно, когда в учебниках алгоритмов быстро они означают с точки зрения вычислительной сложности. То есть количество операций на бит ввода. В общем, они не заботятся о константах, поэтому, если у вас есть вход n бит, требуется ли две операции на бит или сто операций на бит, мы говорим, что алгоритм принимает O (n) времени. Это связано с тем, что если у нас есть алгоритм, который работает в O (n^2) времени (многочлен ... в данном случае, квадрат) и мы представляем себе алгоритм O(), который выполняет 100 операций за бит по сравнению с нашим алгоритмом, который может выполнять 1 операцию на бит, как только размер ввода составляет 100 бит, алгоритм полинома начинает работать очень медленно очень быстро (по сравнению с другим алгоритмом). По существу, вы можете представить две строки: y=100x
и y=x^2
. Возможно, ваш учитель сделал упражнение в алгебре (возможно, это было исчисление?), Где вы должны сказать, какой из них больше, поскольку x подходит к бесконечности. На самом деле это ключевая концепция в расхождении/сближении в исчислении, если вы уже там уже по математике. Независимо от того, с небольшим количеством алгебры, вы можете себе представить наши графики пересекаются в x=100
и y=x^2
быть больше для всех точек, где х больше, чем 100.
Насколько большинство учебников беспокоит, O (nlgn) или лучше считается «быстрым».Одним из примеров очень плохой алгоритм для решения этой задачи будет следующим:
crappyMultiplicationAlg(int a, int b)
int product = 0
for (b>0)
product = product + a
b = b-1
return product
Этот алгоритм в основном использует «Ъ» в качестве счетчика и просто продолжает добавлять «а» до некоторой переменной для каждого времени б отсчитывает. Чтобы вычислить, насколько «быстрый» алгоритм (с точки зрения алгоритмической сложности), мы подсчитываем, сколько будет выполняться разных компонентов. В этом случае мы имеем только цикл for
и некоторую инициализацию (которая в этом случае незначительна, игнорирует ее). Сколько раз работает цикл for
? Вы можете сказать: «Эй, парень! Он работает только« b »раз! Это может быть даже не половина вход. То есть путь лучше чем O (n) время!"
Хитрость здесь в том, что мы имеем дело с размером входа с точки зрения хранения ... и все мы (должны) знать, что для хранения п разрядное целое число, нам нужно Л.Г. n бит. Другими словами, если у нас есть бит x, мы можем сохранить любое (без знака) число до (2^x) -1. В результате, если мы используем стандартное 4-байтовое целое число, это число может составлять до 2^32 - 1, что является хорошим числом в миллиардах, если моя память служит мне правильной. Если вы не доверяете мне, запустите этот алгоритм с числом, равным 10 000 000, и посмотрите, сколько времени потребуется. Все еще не убежден? Используйте номер long
, чтобы использовать номер, например, 1,000,000,000.
Поскольку вы не просили помощи в алгоритме, я оставляю его для вас как упражнение по домашнему заданию (не пытаясь быть рывком, я - проблема с полным выводом и любовью). Если вам нужна помощь, не стесняйтесь спрашивать! Я уже набрал некоторые подсказки случайно, так как я не читал ваш вопрос правильно сначала.
EDIT: Я случайно сделал дерьмовый умножение алгоритм. Примером страшном алгоритма действительно разделением (я изменял) будет:
AbsolutelyTerribleDivisionAlg(int a, int b)
int quotient = 0
while crappyMultiplicationAlg(int b, int quotient) < a
quotient = quotient + 1
return quotient
Этот алгоритм плохо для целого букета причин, не в последнюю очередь из которых является использование моего дерьмовый алгоритма умножения (который будет называться более одного раза даже при относительно «ручном» запуске). Даже если бы нам разрешили использовать оператор *
, хотя это по-прежнему очень плохой алгоритм, во многом благодаря тому же механизму, который использовался в моем ужасном мультиальге.
PS Возможно, в моих двух перечнях есть ошибка забора или два ... я отправил их больше для концептуальной ясности, чем правильности. Независимо от того, насколько точны они при выполнении умножения или деления, они никогда не используют их. Они дадут вашему герпесу вашего ноутбука, а затем заставят его сгореть в результате взрыва серы.
очевидным решение обучал в начальной школе: по двоичное представление: и, или, xor и сдвиг бит. –
Ищите волосы, которые нужно разбить в описании проблемы: 'n/d' не использует *,' n * d⁻¹' avoids /. Если _both_ не должен был использоваться, проблема могла бы заявить об этом или прочитать _использование ни '/', ни '*' _. – greybeard
@greybeard - конечно "без использования ... или ..." ⇔ ", не используя ни ... ни ...", или у меня есть сплит-концы? – Joe