Mam następujący algorytm, który wyszukuje duplikaty i usuwa je:
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;
}
Usiłuję znaleźć najgorszą złożoność tego przypadku. Wiem, że jest to połączenie nlog(n)
, a w mojej pętli for iteruję cały zestaw danych, więc byłoby to liczone jako n
. Nie jestem jednak pewien, co zrobić z tymi liczbami. Czy powinienem je po prostu zsumować? Gdybym to zrobił, jak miałbym to zrobić?
algorithms
algorithm-analysis
big-o
chopper draw lion4
źródło
źródło
Odpowiedzi:
Dla złożoności Big O wszystko, na czym ci zależy, to dominujący termin.
n log(n)
dominuje,n
więc to jedyny termin, na którym ci zależy.źródło
f(n) is O(g(n))
, tak naprawdę mówimy, że jest to funkcjaf is a member of the set of functions that grows at the rate of at most g(n) over the long term
. Oznacza to, że wszyscy członkowieO(n)
są również członkamiO(n*log(n))
.+
W wyrażeniach lubiąO(f(n)) + O(g(n))
rzeczywiście odnoszą się do ustawionej Unii (co naprawdę jesteś pedantyczny, naprawdę powinny korzystać ∪).A + B = { a + b | a in A, b in B }
. Zdarza się, że dla zbiorów postaciO(g(n))
jest to to samo, co zbiór jedności, ponieważ jeden ze zbiorów jest zawsze podzbiorem drugiego i oba są niezmienne w stosunku do sum (tj. A + A = A). (Ups, Nate napisał zasadniczo to samo).Prześledźmy naszą drogę i pamiętajmy definicję
O
. Ten, którego zamierzam użyć, to limit w nieskończoności.Masz rację, twierdząc, że wykonać dwie operacje z odpowiednimi asymptotyczne granice
O(n)
iO(nlog(n))
ale łącząc je w jeden związany nie jest tak proste jak dodanie dwie funkcje. Wiesz, że twoja funkcja zajmuje przynajmniejO(n)
czas, a także przynajmniejO(nlog(n))
czas. Tak naprawdę klasa złożoności dla funkcji jest sumąO(n)
iO(nlog(n))
aleO(nlog(n))
jest rozszerzeniemO(n)
tak naprawdę jest to po prostuO(nlog(n))
.źródło
Jeśli zamierzasz ustawić go z długim czasem, wyglądałoby to mniej więcej tak:
Załóżmy, że całkowity czas to: an + bn log (n), gdzie aib są stałymi (ignorując terminy niższego rzędu).
Gdy n idzie do nieskończoności (an + bn log (n)) / n log (n) -> a / log (n) + b -> b
Zatem całkowity czas wynosi O (bn log (n)) = O (n log (n)).
źródło
Zacznij od definicji O ():
O (n log n) oznacza „mniej niż C n log n, jeśli n jest duże”.
O (n) oznacza „mniej niż D n, jeśli n jest duże”.
Jeśli dodasz oba, wynik będzie mniejszy niż C n log n + D n <C n log n + D n log n <(C + D) n log n = O (n log n).
Ogólnie, jeśli f (n)> C g (n) dla dużego n, a niektóre C> 0, to O (f (n)) + O (g (n)) = O (f (n)). A po wykonaniu kilku przypadków przy użyciu definicji O () będziesz wiedział, co możesz, a czego nie możesz zrobić.
źródło
Duża notacja O jest zdefiniowana jako zbiór:
Zawiera więc wszystkie funkcje, które - zaczynając od jakiegoś dużego punktu - zawsze są mniejsze niż g.
Teraz, gdy masz funkcję, która jest włączona, a następnie uruchom inną, która zwiększa się wolniej niż g, z pewnością rośnie wolniej niż 2 g. Wykonanie czegokolwiek wolniejszego niż g nie zmieni klasy złożoności.
Bardziej formalnie:
Możesz to łatwo udowodnić.
TL; DR
To jest nadal
źródło