Почему мы игнорируем коэффективность в нотации Big O?

При поиске ответов, относящихся к нотации "Big O", я видел много ответов SO, таких как this, this или , но все же я не совсем понял некоторые моменты.

Почему мы игнорируем коэффициенты эффективности?

Например этот ответ говорит, что окончательная сложность 2N + 2 равна O(N); мы удалим ведущий коэффициент 2 и конечную константу 2.

Удаление конечной константы 2 возможно понятно. В конце концов, N может быть очень большим и поэтому "забыть" окончательный 2 может только изменить общий итог на небольшой процент.

Однако я не могу понять, как удалить ведущий коэф. Если верхний 2 выше стал 1 или 3, процентное изменение к общей сумме будет большим.

Аналогично, очевидно, 2N^3 + 99N^2 + 500 O(N^3). Как мы игнорируем 99N^2 вместе с 500?

Ответы

Ответ 1

Цель записи Big-O состоит в том, чтобы найти то, что является доминирующим фактором в асимптотическом поведении функции, поскольку значение стремится к бесконечности.

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

Представьте f(n) = n^3+n^2. По мере того как n переходит в бесконечность, n^2 становится менее актуальным по сравнению с n^3.

Но это просто интуиция, лежащая в основе определения. На практике мы игнорируем некоторые части функции из-за формального определения:

f(x) = O(g(x)) как x->infinity

тогда и только тогда, когда существует положительная вещественная M и вещественная x_0 такая, как

|f(x)| <= M|g(x)| для всех x > x_0.

Это в wikipedia. На самом деле это означает, что есть точка (после x_0), после которой несколько кратных g(x) доминируют f(x). Это определение действует как свободная верхняя граница значения f(x).

Из этого можно получить много других свойств, таких как f(x)+K = O(f(x)), f(x^n+x^n-1)=O(x^n) и т.д. Это просто вопрос использования определения, чтобы доказать это.

В частности, интуиция за удалением коэффициента (K*f(x) = O(f(x))) заключается в том, что мы пытаемся измерить с вычислительной сложностью. В конечном счете это все о времени (или любом ресурсе, на самом деле). Но трудно понять, сколько времени занимает каждая операция. Один алгоритм может выполнять операции 2n, а другой n, но последний может иметь большое постоянное время, связанное с ним. Поэтому для этой цели нелегко рассуждать о разнице между n и 2n.

Ответ 2

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

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

Обозначение Big-O (Ландау) берет свое начало независимо в теории чисел, где одним из его применений является создание своего рода эквивалентности между функциями: если данная функция ограничена сверху другой и одновременно ограничена снизу масштабированной версия той же самой другой функции, то две функции по существу одинаковы с асимптотической точки зрения. Определение Big-O (на самом деле, "Big-Theta" ) фиксирует эту ситуацию: "Big-O" (Theta) двух функций в точности равны.

Тот факт, что запись Big-O позволяет нам игнорировать ведущую константу при сравнении роста функций, делает Big-O идеальным средством измерения различных качеств алгоритмов при соблюдении (игнорировании) оптимизаций "freebie", предлагаемых Linear Теорема о ускорении.

Ответ 3

Другое дело, что, что я понял, сложность 2N ^ 3 + 99N ^ 2 + 500 будет O (N ^ 3). Итак, как мы вообще игнорируем/удаляем часть 99N ^ 2? Разве это не будет иметь значения, если сказать, что N - один миллион?

Итак, в этом случае член 99N ^ 2 far затмевается 2N ^ 3. Точка, в которой они пересекаются, составляет N = 49,5, что намного меньше миллиона.

Но вы воспитываете хороший момент. Асимптотический анализ сложности вычислений на самом деле часто критикуется за игнорирование постоянных факторов, которые могут иметь огромное значение в реальных приложениях. Однако big-O по-прежнему является полезным инструментом для сбора эффективности алгоритма в нескольких слогах. Часто бывает, что алгоритм n^2 будет быстрее в реальной жизни, чем алгоритм n^3 для нетривиального n, и почти всегда тот факт, что алгоритм log(n) будет намного быстрее алгоритма n^2,

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

Ответ 4

Big O обеспечивает хорошую оценку того, какие алгоритмы более эффективны для больших ресурсов, при прочих равных условиях; поэтому для алгоритма с n ^ 3 и множителем n ^ 2 мы пренебрегаем коэффициентом n ^ 2, так как даже если множитель n ^ 2 имеет большую константу, он в конечном итоге будет доминировать n ^ 3-фактором.

Однако реальные алгоритмы включают более простой анализ Big O, например, алгоритм сортировки часто начинается с алгоритма разбиения O (n * log (n)), такого как quicksort или mergesort, и когда разделы становятся достаточно маленькими, алгоритм переключится на более простой алгоритм O (n ^ 2), такой как insertionsort - для небольших входов insertionsort, как правило, быстрее, хотя базовый анализ Big O не показывает этого.

Постоянные факторы часто не очень интересны, и поэтому они опускаются - конечно, разница в факторах порядка 1000 интересна, но обычно разница в факторах меньше, а затем существует много других постоянных факторов считать, что они могут доминировать над константами алгоритмов. Скажем, у меня есть два алгоритма: первый с временем работы 3 * n, второй - с временем работы 2 * n, каждый со сравнимой пространственной сложностью. Этот анализ предполагает равномерный доступ к памяти; что, если первый алгоритм лучше взаимодействует с кешем, и это более чем компенсирует худший постоянный фактор? Что делать, если к нему можно применить более оптимизацию компилятора или лучше работает с подсистемой управления памятью или требует менее дорогостоящего ввода-вывода (например, меньше обращений к диску или меньше соединений базы данных или что-то еще) и т.д.? Постоянный фактор для алгоритма имеет значение, но есть еще много констант, которые необходимо учитывать. Часто самый простой способ определить, какой из алгоритмов лучше всего, - просто запустить их как на некоторых выборках, так и на время результатов; чрезмерная зависимость от постоянных факторов алгоритмов скроет этот шаг.

Ответ 5

Математическая причина:

Настоящая причина, по которой мы это делаем, - это способ определения Big O-Notation: Ряд (или позволяет использовать функцию слова) f (n) находится в O (g (n)), когда ряд f (n)/g (n) ограничен. Пример:

f (n) = 2 * n ^ 2
g (n) = n ^ 2

f (n) находится в O (g (n)), потому что (2 * n ^ 2)/(n ^ 2) = 2 при приближении п к бесконечности. Член (2 * n ^ 2)/(n ^ 2) не становится бесконечно большим (его всегда 2), поэтому фактор ограничен и, следовательно, 2 * n ^ 2 находится в O (n ^ 2).

Другой:

f (n) = n ^ 2
g (n) = n

Термин n ^ 2/n (= n) становится бесконечно большим, так как n переходит в бесконечность, поэтому n ^ 2 не находится в O (n).

Тот же принцип применяется, если у вас

f (n) = n ^ 2 + 2 * n + 20
g (n) = n ^ 2

(n ^ 2 + 2 * n + 20)/(n ^ 2) также ограничено, поскольку оно стремится к 1, так как n переходит в бесконечность.


Big-O Notation в основном описывает, что ваша функция f (n) (от некоторого значения n до бесконечности) меньше функции g (n), умноженной на константу. В предыдущем примере:

2 * n ^ 2 находится в O (n ^ 2), так как мы можем найти значение C, так что 2 * n ^ 2 меньше C * n ^ 2. В этом примере мы можем выбрать C, например, 5 или 10, и условие будет выполнено.

Итак, что вы получаете от этого? Если вы знаете, что ваш алгоритм имеет сложность O (10 ^ n), и вы вводите список из 4 чисел, это может занять короткое время. Если вы вводите 10 номеров, это займет миллион раз! Если это в миллион раз больше или в 5 миллионов раз больше, это не имеет особого значения. Вы можете всегда использовать еще 5 компьютеров для этого и запустить его за такое же количество времени, настоящая проблема заключается в том, что он очень сильно масштабируется с размером ввода.

Ответ 6

Нотация Big O не является абсолютной мерой сложности.

Скорее это определение того, как сложность изменится по мере изменения переменной. Другими словами, при увеличении N сложность будет увеличиваться Big O (f (N)).

Чтобы объяснить, почему термины не включены, мы рассмотрим, как быстро растут члены.

Итак, Big O (2n + 2) имеет два члена 2n и 2. Глядя на скорость увеличения Big O (2) этот термин никогда не будет увеличиваться, это не способствует увеличению темпа роста, так что он уходит. Кроме того, поскольку 2n растет быстрее, чем 2, 2 превращается в шум, когда n становится очень большим.

Аналогично Big O (2n ^ 3 + 99n ^ 2) сравнивает Big O (2n ^ 3) и Big O (99n ^ 2). Для малых значений, например, n < 50, 99n ^ 2 будет вносить больший номинальный процент, чем 2n ^ 3. Однако, если n становится очень большим, скажем 1000000, то 99n ^ 2, хотя номинально большой, он незначителен (близок к 1 миллионному) по сравнению с размером 2n ^ 3.

Как следствие, Big O (n ^ i) Big O (n ^ (i + 1)).

Коэффициенты удаляются из-за математического определения Big O.

Для упрощения определения говорят, что Big O (f (n)) = Big O (f (cn)) для константы c. Это нужно принимать на веру, потому что причина этого является чисто математической, и поэтому доказательство будет слишком сложным и сухим, чтобы объяснить простым языком.

Ответ 7

Для практических применений константы имеют значение, поэтому O(2 n^3) будет лучше, чем O(1000 n^2) для входов с n меньше 500.

Здесь есть две основные идеи: 1) Если ваш алгоритм должен быть отличным для любого ввода, он должен иметь низкую временную сложность и 2), что n^3 растет намного быстрее, чем n^2, что perfering n^3 более n^2 почти никогда не имеет смысла.