Алгоритмы: как мне сложить O (n) и O (nlog (n)) вместе?

22

У меня есть следующий алгоритм, который находит дубликаты и удаляет их:

public static int numDuplicatesB(int[] arr) {
    Sort.mergesort(arr);
    int numDups = 0;
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] == arr[i - 1]) {
            numDups++;
} }
    return numDups;
}

Я пытаюсь найти наихудший случай сложности времени. Я знаю, что mergesort есть nlog(n), и в моем цикле for я выполняю итерацию по всему набору данных, чтобы это считалось n. Я не уверен, что делать с этими числами, хотя. Должен ли я просто сложить их вместе? Если бы я это сделал, как бы я это сделал?

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

Ответы:

67
O(n) + O(n log(n)) = O(n log(n))

Для сложности Big O все, что вас волнует, это доминирующий термин. n log(n)доминирует, nтак что это единственный термин, который вас волнует.

Джастин Кейв
источник
4
Еще один способ подумать об этом - представить, что ваша обработка O (n) была действительно O (n log n), как будто вы делали два независимых вида. Тогда у тебя будет 2 * O (n log n). Но константы отбрасываются, так что вы вернулись к O (n log n).
Джонатан Юнис
4
@Jonathan Хотя это работает на практике, очень верно, что O (n) не равно O (n log (n)), поэтому я бы не советовал использовать это на регулярной основе.
Aza
17
@ Emrakul на самом деле я думаю, что рассуждения теоретически обоснованы, а также практичны. O (n) является правильным подмножеством O (n log (n)). Поэтому, если f (n) принадлежит O (n), оно также принадлежит O (n log (n)).
Эмори
17
Следует отметить, что когда мы говорим, f(n) is O(g(n))мы действительно говорим, что функция f is a member of the set of functions that grows at the rate of at most g(n) over the long term. Это означает, что все члены O(n)также являются членами O(n*log(n)). +В таких выражениях , как на O(f(n)) + O(g(n))самом деле относится к множественному объединению (что вы действительно педантичными, вы действительно должны использовать ∪).
Ли Райан
3
@LieRyan Первоначально он не установлен союз, но множественная сумма: A + B = { a + b | a in A, b in B }. Бывает, что для наборов формы O(g(n))это то же самое, что и объединение множеств, поскольку один из наборов всегда является подмножеством другого, и оба они инвариантны к суммам (т. Е. A + A = A). (Ой, Нейт действительно написал то же самое).
Пауло Эберманн
56

Давайте рассмотрим наш путь и вспомним определение O. Тот, который я собираюсь использовать, для предела в бесконечности.

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

davidk01
источник
12
+1 это должен быть ответ. Он описывает ответ более точно, используя сложные термины.
5

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

Предположим, что общее время: an + bn log (n), где a и b - константы (игнорируя члены более низкого порядка).

Когда n переходит в бесконечность (an + bn log (n)) / n log (n) -> a / log (n) + b -> b

Таким образом, общее время O (bn log (n)) = O (n log (n)).

richardb
источник
2

Начнем с определения O ():

O (n log n) означает «меньше, чем C n log n, если n большое».

O (n) означает «меньше, чем D n, если n большое».

Если вы добавите оба, результат будет меньше C n log n + D n <C n log n + D n log n <(C + D) n log n = O (n log n).

В общем, если f (n)> C g (n) для больших n и некоторого C> 0, то O (f (n)) + O (g (n)) = O (f (n)). И после нескольких случаев использования определения O () вы будете знать, что вы можете и не можете сделать.

gnasher729
источник
1

Большая нотация O определяется как набор:

введите описание изображения здесь

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

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

Более формально:

f, h \ in \ mathcal {O} (g) \ Rightarrow (f + h) \ in \ mathcal {O} (g)

Вы можете легко доказать это.

TL; DR

Это все еще n log (n)

Мартин Тома
источник