Big O, как вы рассчитываете / приближаете это?

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

Например, если ваше приложение разблокирует функции только в том случае, если пользователь находится в определенном месте (например, в вашем магазине), вы можете проверить gps, а также сотовые башни. В настоящее время ни одно приложение для спуфинга gps также не обманывает башни сотовых телефонов, поэтому вы можете увидеть, пытается ли кто-то по всей стране просто подтолкнуть их к вашим особым функциям (например, я думаю о приложении Disney Mobile Magic на одном примере).

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

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

841
задан Community 24 February 2011 в 07:56
поделиться

15 ответов

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

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

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

4
ответ дан JB King 24 February 2011 в 07:56
поделиться

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

Как очень простой пример говорят, что Вы хотели сделать проверку работоспособности на скорости вида списка платформы.NET. Вы могли записать что-то как следующее, затем проанализировать результаты в Excel, чтобы удостовериться, что они не превысили n*log (n) кривая.

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

int nCmp = 0;
System.Random rnd = new System.Random();

// measure the time required to sort a list of n integers
void DoTest(int n)
{
   List<int> lst = new List<int>(n);
   for( int i=0; i<n; i++ )
      lst[i] = rnd.Next(0,1000);

   // as we sort, keep track of the number of comparisons performed!
   nCmp = 0;
   lst.Sort( delegate( int a, int b ) { nCmp++; return (a<b)?-1:((a>b)?1:0)); }

   System.Console.Writeline( "{0},{1}", n, nCmp );
}


// Perform measurement for a variety of sample sizes.
// It would be prudent to check multiple random samples of each size, but this is OK for a quick sanity check
for( int n = 0; n<1000; n++ )
   DoTest(n);
5
ответ дан Eric 24 February 2011 в 07:56
поделиться

Сломайте алгоритм в части, Вы знаете большую нотацию O для, и объединение через большие операторы O. Это - единственный способ, о котором я знаю.

Для получения дополнительной информации, проверьте страница Wikipedia на предмете.

7
ответ дан Lasse Vågsæther Karlsen 24 February 2011 в 07:56
поделиться

Знакомство с алгоритмами/структурами данных я использую и/или быстрый анализ взгляда итеративного вложения. Трудность состоит в том при вызове библиотечной функции, возможно многократно - можно часто быть не уверены в том, вызываете ли Вы функцию излишне время от времени или какую реализацию они используют. Возможно, библиотечные функции должны иметь меру по сложности/эффективности, ли это быть Большим O или некоторой другой метрикой, которая доступна в документации или даже IntelliSense.

7
ответ дан Peter Mortensen 24 February 2011 в 07:56
поделиться

В основном вещь, которая неожиданно возникает 90% времени, просто анализирует циклы. У Вас есть единственные, дважды, тройные вложенные циклы? Вы имеют O (n), O (n^2), O (n^3) время выполнения.

Очень редко (если Вы не пишете платформу с обширной основной библиотекой (как, например.NET BCL или STL C++) Вы встретитесь с чем-либо, что более трудно, чем просто рассмотрение Ваших циклов (для операторов, в то время как, goto, и т.д....)

10
ответ дан Adam 24 February 2011 в 07:56
поделиться

Большая нотация O полезна, потому что это легко работать с и скрывает ненужные сложности и детали (для некоторого определения ненужных). Один хороший способ разработать сложность деления и завоевывает алгоритмы, древовидный метод. Скажем, у Вас есть версия quicksort со средней процедурой, таким образом, Вы разделяете массив на отлично сбалансированные подмассивы каждый раз.

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

, Так как мы можем найти медиану в O (n) временем и разделить массив в двух частях в O (n) время, работа, сделанная в каждом узле, является O (k), где k является размером массива. Каждый уровень дерева содержит (самое большее) целый массив, таким образом, работа на уровень является O (n) (размеры подмассивов составляют в целом n, и так как у нас есть (К) O на уровень, мы можем сложить это). Существует только журнал (n) уровни в дереве с каждого раза, когда мы делим на два вход.

Поэтому мы можем верхняя граница объем работы O (n*log (n)).

Однако Большой O скрывает некоторые детали, которые мы иногда не можем игнорировать. Рассмотрите вычисление последовательности Fibonacci с

a=0;
b=1;
for (i = 0; i <n; i++) {
    tmp = b;
    b = a + b;
    a = tmp;
}

, и позволяет, просто принимают a, и b является BigIntegers в Java или чем-то, что может обработать произвольно большие количества. Большинство людей сказало бы, что это - O (n) алгоритм без вздрагивания. Обоснование состоит в том, что у Вас есть n повторения в для цикла и O (1) работа в стороне цикл.

, Но Числа Фибоначчи являются большими, энное Число Фибоначчи экспоненциально в n поэтому просто хранение, это возьмет порядок n байтов. Выполнение дополнения с большими целыми числами возьмет O (n) объем работы. Таким образом, общая сумма работы, сделанной в этой процедуре,

1 + 2 + 3 +... + n = n (n-1)/2 = O (n^2)

Так этот алгоритм выполнения в квадратичное время!

8
ответ дан 24 February 2011 в 07:56
поделиться

Если Вы хотите оценить порядок своего кода опытным путем, а не путем анализа кода, Вы могли всунуть ряд увеличивания стоимостей n и время Вашего кода. Выведите свои синхронизации на печать на логарифмической шкале. Если код является O (x^n), значения должны упасть на строку наклона n.

Это имеет несколько преимуществ просто изучение кода. С одной стороны, Вы видите, являетесь ли Вы в диапазоне, где время выполнения приближается к своему асимптотическому порядку. Кроме того, можно найти, что некоторый код, что Вы думали, был порядком O (x), действительно порядок O (x^2), например, из-за времени, проведенного в вызовах библиотеки.

14
ответ дан John D. Cook 24 February 2011 в 07:56
поделиться

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

Также я хотел бы добавить, как это сделано для [1 122] рекурсивные функции :

предполагают, что у нас есть функция как ( код схемы ):

(define (fac n)
    (if (= n 0)
        1
            (* n (fac (- n 1)))))

, который рекурсивно вычисляет факториал данного числа.

первый шаг должен попытаться определить рабочую характеристику для тело функции [только 118] в этом случае, ничто специальное не сделано в теле, просто умножение (или возврат значения 1).

Так производительность для тела: O (1) (постоянный).

Следующий пытаются определить это для количество рекурсивных вызовов . В этом случае у нас есть n-1 рекурсивные вызовы.

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

Тогда соединяет те два, и у Вас тогда есть производительность для целой рекурсивной функции:

1 * (n-1) = O (n)

<час>

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

28
ответ дан Community 24 February 2011 в 07:56
поделиться

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

Это означает, что между алгоритмом в O (n) и один в O (n <глоток> 2 ), самым быстрым является не всегда первый (хотя там всегда существует значение n, таким образом, что для проблем размера> n, первый алгоритм является самым быстрым).

Примечание, что скрытая константа очень зависит от реализации!

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

существуют различные сложности времени:

  • Худший случай (обычно самое простое для выяснения, хотя не всегда очень значимый)
  • Средний случай (обычно намного тяжелее для выяснения...)

  • ...

А хорошее введение Введение в Анализ Алгоритмов R. Sedgewick и P. Flajolet.

, Как Вы говорите, premature optimisation is the root of all evil, и (если возможный) профилирование действительно должно всегда использоваться при оптимизации кода. Это может даже помочь Вам определить сложность своих алгоритмов.

42
ответ дан nbro 24 February 2011 в 07:56
поделиться

При знании, как выяснить, Большое время O для конкретной проблемы полезно, зная, что некоторые общие случаи могут иметь большое значение в помощи Вам принять решения в Вашем алгоритме.

Вот некоторые наиболее распространенные случаи, снятые от http://en.wikipedia.org/wiki/Big_O_notation#Orders_of_common_functions :

O (1) - Определение, если число даже или нечетно; использование таблицы поиска постоянного размера или хэш-таблицы

O (logn) - Нахождения объекта в сортированном массиве с двоичным поиском

O (n) - Нахождение объекта в неотсортированном списке; добавление двух N-разрядных чисел

O (n <глоток> 2 ) - Умножение двух N-разрядных чисел простым алгоритмом; добавление двух nГ — n матрицы; пузырьковая сортировка или вид вставки

O (n <глоток> 3 ) - Умножение двух nГ — n матрицы простым алгоритмом

O (c <глоток> n ) - Нахождение (точного) решения проблемы коммивояжера с помощью динамического программирования; определение, являются ли два логических оператора эквивалентной грубой силой использования

O (n!) - Решение проблемы коммивояжера через поиск "в лоб"

O (n <глоток> n ) - Часто используемый вместо O (n!) для получения более простых формул для асимптотической сложности

94
ответ дан nbro 24 February 2011 в 07:56
поделиться

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

Несколько примеров того, как это используется в коде C.

Говорят, что у нас есть массив n элементов

int array[n];

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

x = array[0];

, Если мы хотели найти число в списке:

for(int i = 0; i < n; i++){
    if(array[i] == numToFind){ return i; }
}

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

, Когда мы добираемся до вложенных циклов:

for(int i = 0; i < n; i++){
    for(int j = i; j < n; j++){
        array[j] += 2;
    }
}

Это - O (n^2) с тех пор для каждой передачи внешнего цикла (O (n)), мы должны пройти весь список снова, таким образом, n's умножается, отъезд нас с n придал квадратную форму.

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

199
ответ дан DShook 24 February 2011 в 07:56
поделиться

Менее полезный обычно, я думаю, но ради полноты существует также Большая Омега О© , который определяет нижнюю границу на сложности алгоритма, и Большая Тета О ˜ , который определяет и верхнюю и нижнюю границу.

8
ответ дан Peter Mortensen 24 February 2011 в 07:56
поделиться

То, что часто пропускается, , ожидал поведение Ваших алгоритмов. Это не изменяет Большой-O из Вашего алгоритма , но это действительно касается оператора "преждевременная оптимизация...."

Ожидаемое поведение Вашего алгоритма - очень dumbed вниз - как быстро можно ожидать, что алгоритм будет работать над данными, которые Вы, скорее всего, будете видеть.

, Например, при поиске значения в списке это - O (n), но если Вы знаете, что большинство списков, которые Вы видите, имеет Ваше значение, честное, типичное поведение Вашего алгоритма быстрее.

Для реального закрепления его необходимо ли быть в состоянии описать распределение вероятностей "входного пространства" (если необходимо отсортировать список, как часто тот список уже собирается быть отсортированным? как часто это полностью инвертируется? как часто это главным образом отсортировано?) Не всегда выполнимо, что Вы знаете, что, но иногда делаете.

4
ответ дан Baltimark 24 February 2011 в 17:56
поделиться

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

, Если Вы действительно хотите ответить на свой вопрос для какого-либо алгоритма лучшее, можно сделать, должен применить теорию. Кроме того, упрощенного "худшего случая" анализ я нашел Амортизируемый анализ очень полезный на практике.

6
ответ дан Suma 24 February 2011 в 17:56
поделиться

Я думаю об этом с точки зрения информации. Любая проблема состоит из изучения определенного числа битов.

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

, Например, if оператор, имеющий два ответвления, оба, одинаково вероятно, имеет энтропию 1/2 * журнал (2/1) + 1/2 * журнал (2/1) = 1/2 * 1 + 1/2 * 1 = 1. Таким образом, его энтропия составляет 1 бит.

предположим Вы ищете таблицу объектов N, как N=1024. Это - 10-разрядная проблема потому что журнал (1024) = 10 битов. Таким образом, если можно искать его с операторами IF, которые имеют одинаково вероятные результаты, это должно принять 10 решений.

Это - то, что Вы получаете с двоичным поиском.

предположим Вы делаете линейный поиск. Вы смотрите на первый элемент и спрашиваете, является ли это то, Вы хотите. Вероятности являются 1/1024, что это, и 1023/1024, который это не. Энтропия того решения является 1/1024*log (1024/1) + 1023/1024 * журнал (1024/1023) = 1/1024 * 10 + 1023/1024 * приблизительно 0 = приблизительно.01 бит. Вы изучили очень мало! Второе решение не намного лучше. Именно поэтому линейный поиск является настолько медленным. На самом деле это экспоненциально в числе битов, которые необходимо изучить.

предположим Вы делаете индексацию. Предположим, что таблица предварительно отсортирована в большое количество мусорных ведер, и Вы используете некоторые все биты в ключе для индексации непосредственно к записи таблицы. Если существует 1 024 мусорных ведра, энтропия является 1/1024 * журнал (1024) + 1/1024 * журнал (1024) +... для всех 1 024 возможных результатов. Это - 1/1024 * 10 раз 1 024 результата, или 10 битов энтропии для той одной операции индексации. Именно поэтому индексация поиска быстра.

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

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

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

22
ответ дан nbro 24 February 2011 в 17:56
поделиться