Существуют ли какие-либо O (1/n) алгоритмы?

Существуют ли какие-либо O (1/n) алгоритмы?

Или что-нибудь еще меньшее, чем O (1)?

Ответ 1

Этот вопрос не так глуп, как может показаться. По крайней мере, теоретически, что-то вроде O (1/n) совершенно разумно, когда мы берем математическое определение обозначения Big O:

Теперь вы можете легко заменить g (x) на 1/x... очевидно, что приведенное выше определение все еще верно для некоторого f.

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

def get_faster(list):
    how_long = (1 / len(list)) * 100000
    sleep(how_long)

Понятно, что эта функция тратит меньше времени по мере увеличения размера ввода… по крайней мере, до некоторого предела, навязанного аппаратными средствами (точность чисел, минимум времени ожидания в sleep, время обработки аргументов и т.д.): Тогда этот предел постоянная нижняя граница, так что фактически вышеприведенная функция все еще имеет время выполнения O (1).

Но на самом деле существуют реальные алгоритмы, в которых время выполнения может уменьшаться (хотя бы частично) при увеличении размера ввода. Обратите внимание, что эти алгоритмы не будут демонстрировать поведение во время выполнения ниже O (1). Тем не менее, они интересные. Например, возьмем очень простой алгоритм поиска текста Хорспула. Здесь ожидаемое время выполнения будет уменьшаться по мере увеличения длины шаблона поиска (но увеличение длины стога сена снова увеличит время выполнения).

Ответ 2

Да.

Существует ровно один алгоритм с временем выполнения O (1/n), "пустой" алгоритм.

Для алгоритма O (1/n) означает, что он выполняет асимптотически меньше шагов, чем алгоритм, состоящий из одной команды. Если он выполняется менее чем за один шаг для всех n > n0, он должен состоять из точно никакой инструкции вообще для тех n. Поскольку проверка "если n > n0" стоит как минимум 1 команда, она не должна содержать никакой инструкции для всех n.

Подведение итогов: Единственным алгоритмом, который является O (1/n), является пустой алгоритм, не состоящий из инструкции.

Ответ 3

Это невозможно. Определение Big-O не превосходит неравенства:

A(n) = O(B(n))
<=>
exists constants C and n0, C > 0, n0 > 0 such that
for all n > n0, A(n) <= C * B(n)

Таким образом, B (n) на самом деле является максимальным значением, поэтому, если он уменьшается с ростом n, оценка не изменится.

Ответ 4

sharptooth верен, O (1) - наилучшая производительность. Тем не менее, это не означает быстрое решение, просто фиксированное решение времени.

Интересный вариант и, возможно, то, что действительно предлагается, - это проблемы, которые становятся легче по мере роста населения. Я могу думать о 1, хотя и придумал и наглость:

Есть ли у двух человек в наборе один день рождения? Когда n превышает 365, верните true. Хотя для менее 365 это O (n ln n). Возможно, это не отличный ответ, так как проблема не медленно становится проще, а просто становится O (1) при n > 365.

Ответ 5

Из моего предыдущего изучения большой нотации O, даже если вам нужен 1 шаг (например, проверка переменной, выполнение задания), это O (1).

Заметим, что O (1) совпадает с O (6), так как "константа" не имеет значения. Поэтому мы говорим, что O (n) совпадает с O (3n).

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

(Если мы решили не делать этого, тогда это может стать вопросом Дзэн или Тао... в области программирования O (1) по-прежнему является минимумом).

Или как об этом:

программист: босс, я нашел способ сделать это в O (1) раз!
босс: не нужно это делать, мы сегодня банкротом.
программист: oh, тогда он становится O (0).

Ответ 6

Нет, это невозможно:

Поскольку n стремится к бесконечности в 1/n, мы в конечном итоге достигаем 1/(inf), что эффективно 0.

Таким образом, большой класс задачи будет O (0) с массивным n, но ближе к постоянному времени с низким n. Это неразумно, поскольку единственное, что может быть сделано быстрее, чем постоянное время:

void nothing() {};

И даже это возможно!

Как только вы выполните команду, у вас есть как минимум O (1), так что нет, у нас не может быть класс O (1/n)!

Ответ 7

Как насчет того, чтобы вообще не запускать функцию (NOOP)? или с использованием фиксированного значения. Это считается?

Ответ 8

Я часто использую O (1/n) для описания вероятностей, которые становятся меньше по мере увеличения входных данных - например, вероятность того, что на лог2 (n) будет отображаться справедливая монета, - это O (1/n).

Ответ 9

O (1) просто означает "постоянное время".

Когда вы добавляете ранний выход в цикл [1], вы (в записи с большим О) превращаете O (1) в O (n), но делаете это быстрее.

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

1: Предполагая длину статического списка для этого примера

Ответ 10

Я считаю, что квантовые алгоритмы могут выполнять множественные вычисления "сразу" через суперпозицию...

Я сомневаюсь, что это полезный ответ.

Ответ 11

Для тех, кто читает этот вопрос и хочет понять, о чем идет речь, это может помочь:

|    |constant |logarithmic |linear|  N-log-N |quadratic|  cubic  |  exponential  |
|  n |  O(1)   | O(log n)   | O(n) |O(n log n)|  O(n^2) |  O(n^3) |     O(2^n)    |
|  1 |       1 |          1 |     1|         1|        1|       1 |             2 |
|  2 |       1 |          1 |     2|         2|        4|       8 |             4 |
|  4 |       1 |          2 |     4|         8|       16|      64 |            16 |
|  8 |       1 |          3 |     8|        24|       64|     512 |           256 |
| 16 |       1 |          4 |    16|        64|      256|   4,096 |         65536 |
| 32 |       1 |          5 |    32|       160|    1,024|  32,768 | 4,294,967,296 |
| 64 |       1 |          6 |    64|       384|    4,069| 262,144 |   1.8 x 10^19 |

Ответ 12

у многих людей был правильный ответ (Нет). Здесь другой способ доказать это: для того, чтобы иметь функцию, вы должны вызвать функцию, и вам нужно вернуть ответ. Это занимает определенное постоянное время. ДАЖЕ ЕСЛИ остальная часть обработки занимает меньше времени для больших входов, распечатка ответа (который мы можем считать одним битом) занимает как минимум постоянное время.

Ответ 14

Если решение существует, оно может быть подготовлено и доступно для доступа в постоянное время = немедленно. Например, используя структуру данных LIFO, если вы знаете, что запрос сортировки выполняется в обратном порядке. Затем данные уже отсортированы, если выбрана соответствующая модель (LIFO).

Ответ 15

Вы не можете идти ниже O (1), однако O (k), где k меньше N, возможно. Мы назвали их сублинейные алгоритмы времени. В некоторых задачах алгоритм сублинейного времени может давать только приблизительные решения конкретной задачи. Однако иногда приближенные решения просто прекрасны, вероятно, потому, что набор данных слишком велик, или что он слишком вычислительно дорог, чтобы вычислить все.

Ответ 16

Какие проблемы становятся проще по мере роста населения? Один ответ - вещь, такая как bittorrent, где скорость загрузки - это обратная функция количества узлов. В отличие от автомобиля, который замедляет работу, чем больше вы его загружаете, сеть обмена файлами, такая как bittorrent, ускоряет подключение большего количества узлов.

Ответ 17

O (1/n) не меньше O (1), это в основном означает, что чем больше данных у вас есть, тем быстрее выполняется алгоритм. Скажем, вы получаете массив и всегда заполняете его до 10 элементов 100 если он имеет меньше этого и ничего не делает, если их больше. Это не O (1/n), конечно, но что-то вроде O (-n):) Слишком плохое O-большое обозначение не допускает отрицательных значений.

Ответ 18

Как уже указывалось, помимо возможного исключения нулевой функции не может быть функций O(1/n), так как при этом время будет приближаться к 0.

Конечно, есть некоторые алгоритмы, подобные тем, которые определены Конрадом, которые, по-видимому, должны быть меньше O(1) по крайней мере в некотором смысле.

def get_faster(list):
    how_long = 1/len(list)
    sleep(how_long)

Если вы хотите исследовать эти алгоритмы, вы должны либо определить собственное асимптотическое измерение, либо собственное понятие времени. Например, в приведенном выше алгоритме я мог бы позволить использовать несколько "свободных" операций определенное количество раз. В приведенном выше алгоритме, если я определяю t ', исключив время для всего, кроме сна, тогда t' = 1/n, что является O (1/n). Вероятно, есть лучшие примеры, поскольку асимптотическое поведение тривиально. На самом деле, я уверен, что кто-то там может придумать чувства, которые дают нетривиальные результаты.

Ответ 19

Большинство остальных ответов интерпретируют big-O исключительно на время работы алгоритма. Но поскольку вопрос не упоминал об этом, я подумал, что стоит упомянуть о другом применении большого числа O в численном анализе, которое связано с ошибкой.

Многие алгоритмы могут быть O (h ^ p) или O (n ^ {- p}) в зависимости от того, говорите ли вы о размере шага (h) или количестве делений (n). Например, в методе Эйлера вы ищете оценку y (h), учитывая, что вы знаете y (0) и dy/dx ( производная от у). Ваша оценка y (h) точнее, чем ближе h к 0. Итак, чтобы найти y (x) для некоторого произвольного x, отнимает интервал 0 до x, разбивает его до n частей и запускает метод Эйлера в каждой точке, получить от y (0) до y (x/n) до y (2x/n) и т.д.

Таким образом, метод Эйлера является алгоритмом O (h) или O (1/n), где h обычно интерпретируется как размер шага, а n интерпретируется как количество раз, когда вы делите интервал.

Вы также можете использовать O (1/h) в приложениях реального численного анализа из-за ошибок округления с плавающей запятой. Чем меньше вы делаете свой интервал, тем больше отменяется реализация определенных алгоритмов, большая потеря значительных цифр и, следовательно, больше ошибок, которые распространяются через алгоритм.

Для метода Эйлера, если вы используете плавающие точки, используйте достаточно маленький шаг и отмену, и вы добавляете небольшое число к большому числу, оставляя большое число неизменным. Для алгоритмов, которые вычисляют производную путем вычитания двух чисел из функции, оцененной в двух очень близких положениях, аппроксимируя y '(x) с (y (x + h) - y (x)/h) в гладких функциях y (x + h) приближается к y (x), что приводит к большому аннулированию и оценке производной с меньшим количеством значимых цифр. Это, в свою очередь, распространяется на любой алгоритм, для которого требуется производная (например, проблема с граничными значениями).

Ответ 20

ОК, я немного подумал об этом, и, возможно, существует алгоритм, который мог бы следовать этой общей форме:

Вам нужно вычислить проблему коммивояжера для 1000 node, однако вам также дается список узлов, которые вы не можете посетить. Поскольку список невидимых узлов увеличивается, проблема становится легче решить.

Ответ 21

Как насчет этого:

void FindRandomInList(list l)
{
    while(1)
    {
        int rand = Random.next();
        if (l.contains(rand))
            return;
    }
}

по мере увеличения размера списка ожидаемое время выполнения программы уменьшается.

Ответ 22

Я вижу алгоритм, равный O (1/n), по общему признанию, верхней границе:

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

Теперь, если он не изменился, вы просто создадите список предметов, выберите один случайным образом и получите время O (1). Однако динамический характер данных исключает составление списка, вам просто нужно случайно опробовать и проверить достоверность зонда. (И обратите внимание, что по существу нет гарантии, что ответ остается в силе, когда он вернется. Это все еще может иметь применение - скажем, ИИ для единицы в игре. Он мог стрелять в цель, которая выпала из поля зрения, когда она была потянув курок.)

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

Ответ 23

В численном анализе алгоритмы аппроксимации должны иметь подпостоянную асимптотическую сложность в допуске аппроксимации.

class Function
{
    public double[] ApproximateSolution(double tolerance)
    {
        // if this isn't sub-constant on the parameter, it rather useless
    }
}

Ответ 24

Я думаю, что меньше, чем O (1) невозможно. Любое время, занимаемое алгоритмом, называется O (1). Но для O (1/n), как насчет функции ниже. (Я знаю, что есть много вариантов, уже представленных в этом решении, но я думаю, что у них всех есть некоторые недостатки (не основные, они хорошо объясняют концепцию). Так что вот один, просто для аргументации:

def 1_by_n(n, C = 10):   #n could be float. C could be any positive number
  if n <= 0.0:           #If input is actually 0, infinite loop.
    while True:
      sleep(1)           #or pass
    return               #This line is not needed and is unreachable
  delta = 0.0001
  itr = delta
  while delta < C/n:
    itr += delta

Таким образом, при увеличении n функция будет занимать все меньше и меньше времени. Также гарантируется, что если input на самом деле равен 0, то функция вернется навсегда.

Можно утверждать, что это будет ограничено точностью машины. таким образом, sinc eit имеет верхнюю границу, это O (1). Но мы также можем обойти это, взяв значения n и C в строку. И сложение и сравнение делается на строку. Идея состоит в том, что при этом мы можем уменьшить n сколь угодно малым. Таким образом, верхний предел функции не ограничен, даже если мы игнорируем n = 0.

Я также считаю, что мы не можем просто сказать, что время выполнения равно O (1/n). Но мы должны сказать что-то вроде O (1 + 1/n)

Ответ 25

Ни один алгоритм на самом деле не имеет времени выполнения O (1/n), но эта нотация может использоваться неофициально для алгоритма, время выполнения которого действительно равно O (m/n), где m большое и не должно изменяться. Вот пример такого алгоритма:

Дан неупорядоченный набор (например, хеш-таблица), содержащий n значений из целочисленного диапазона 0≤x

Мы хотим найти минимальное значение в наборе максимально эффективно.

Если n намного меньше, чем m, то линейное сканирование по значениям в наборе является наиболее эффективным решением (O (n)).

Но если n больше, чем m -, часто будет более эффективно перебирать потенциальные значения, начиная с 0 и повышаясь, проверяя каждое из них, чтобы увидеть, есть ли оно в наборе. Мы, конечно, можем остановиться, как только найдем его, так как он будет самым маленьким.

Ожидаемое количество тестов (при условии, что данные случайным образом распределены по диапазону) составляет m/n. Если мы считаем m константой (так как в реальных приложениях она часто определяется чем-то, что мы не можем легко изменить, например, размером целочисленного типа данных), похоже, что это будет O (1/n) (с большим постоянным коэффициентом m). И это дает точное описание того, как изменяется производительность алгоритма при переходе n от m - √ к m, тогда как m остается неизменным.

Но обозначения не совсем верны. Асимптотическая запись предназначена для описания поведения, когда его переменные члены стремятся к бесконечности. Если бы алгоритм O (1/n) мог работать для n, приближающегося к бесконечности, его время выполнения будет стремиться к нулю, но в члене 1/n будут преобладать постоянные члены (и поэтому O (1) будет лучшим описанием его спектакль). Для алгоритма, который имеет смысл только на ограниченном n, неправильно использовать асимптотические обозначения. Для строгого асимптотического анализа вам также необходимо учитывать переменную ma, чтобы и m, и n могли увеличиваться до бесконечности.

Я подозреваю, что если вы когда-нибудь увидите O (1/n), это будет использоваться как неформальное сокращение для O (m/n).

Ответ 27

Возможно построить алгоритм, который является O (1/n). Одним из примеров был бы цикл, который повторяет несколько кратных f (n) -n раз, где f (n) - некоторая функция, значение которой гарантированно больше n, а предел f (n) -n при приближении n к бесконечности нуль. Расчет f (n) также должен был бы быть постоянным для всех n. Я не знаю, как будет выглядеть f (n) или какое приложение будет иметь такой алгоритм, на мой взгляд, однако такая функция могла бы существовать, но полученный алгоритм не имел бы никакой цели, кроме как доказать возможность использования алгоритма с O (1/п).

Ответ 28

Я не знаю об алгоритмах, но сложность, меньшая, чем O (1), появляется в рандомизированных алгоритмах. На самом деле o (1) (мало o) меньше O (1). Такая сложность обычно возникает в рандомизированных алгоритмах. Например, как вы сказали, когда вероятность какого-либо события имеет порядок 1/n, они обозначают его с помощью o (1). Или, когда они хотят сказать, что что-то происходит с высокой вероятностью (например, 1 - 1/n), они обозначают его 1 - o (1).

Ответ 29

Если ответ один и тот же, независимо от входных данных, тогда у вас есть алгоритм O (0).

или другими словами - ответ известен до подачи входных данных - функция может быть оптимизирована - так что O (0)

Ответ 30

Обозначение Big-O представляет собой наихудший сценарий для алгоритма, который не совпадает с его типичным временем выполнения. Нетрудно доказать, что алгоритм O (1/n) является алгоритмом O (1). По определению,
O (1/n) → T (n) <= 1/n, для всех n >= C > 0
O (1/n) → T (n) <= 1/C, Так как 1/n <= 1/C для всех n >= C
O (1/n) → O (1), так как запись Big-O игнорирует константы (т.е. Значение C не имеет значения)