W większości klas algorytmów wprowadzających wprowadzane są notacje takie jak (Big O) i , a uczeń zazwyczaj uczy się korzystania z jednej z nich w celu znalezienia złożoności czasowej.Θ
Istnieją jednak inne oznaczenia, takie jak , i . Czy są jakieś konkretne scenariusze, w których jedna notacja byłaby lepsza od innej?Ω ω
Odpowiedzi:
Odwołujesz się do notacji Landaua . Nie są to różne symbole tej samej rzeczy, ale mają zupełnie inne znaczenie. To, które jest „preferowane”, zależy całkowicie od pożądanego stwierdzenia.
f g ≤ f ∈ o ( g ) <f∈O(g) oznacza, że rośnie maksymalnie tak szybko jak , asymptotycznie i do stałego współczynnika; pomyśl o tym jak o . jest bardziej rygorystyczną formą, tj . .f g ≤ f∈o(g) <
f g ω f ∈ Ω ( g ) g ∈ O ( f )f∈Ω(g) ma symetryczne znaczenie: rośnie co najmniej tak szybko, jak . jest bardziej surowym kuzynem. Widać, że jest równoważne .f g ω f∈Ω(g) g∈O(f)
f g f ∈ O ( g ) ∩ Ω ( g ) f ∼ g Θ Of∈Θ(g) oznacza, że rośnie tak szybko, jak ; formalnie . (równość asymptotyczna) to jego silniejsza forma. Często mamy na myśli gdy używamy .f g f∈O(g)∩Ω(g) f∼g Θ O
Zwróć uwagę, że i jego rodzeństwo są klasami funkcji . Ważne jest, aby być bardzo świadomym tego i ich dokładnych definicji - które mogą się różnić w zależności od tego, kto mówi - podczas wykonywania z nimi „arytmetyki”.O(g)
Podczas sprawdzania rzeczy staraj się pracować z precyzyjną definicją. Istnieje wiele definicji symboli Landaua (wszystkie z tą samą podstawową intuicją), z których niektóre są równoważne w niektórych zestawach funkcji, ale nie w innych.
Sugerowane czytanie:
Czy O (mn) jest uważany za wzrost „liniowy” czy „kwadratowy”?
Jeśli interesuje Cię rygorystyczne i rzetelne stosowanie notacji Landaua, możesz zainteresować się ostatnimi pracami Rutanena i in. [1] Formułują niezbędne i wystarczające kryteria dla asymptotycznej notacji, gdy używamy ich w algorytmach, pokazują, że wspólna definicja ich nie spełnia i zapewniają (w rzeczywistości) wykonalną definicję.
źródło
Big O: górna granica
„Big O” ( ) jest zdecydowanie najczęstszym. Kiedy analizujesz złożoność algorytmu, przez większość czasu liczy się górna granica tego, jak szybko rośnie czas pracy¹, gdy rośnie wielkość danych wejściowych. Zasadniczo chcemy wiedzieć, że uruchomienie algorytmu nie zajmie „zbyt długo”. Nie możemy tego wyrazić w rzeczywistych jednostkach czasu (sekundach), ponieważ zależałoby to od dokładnej implementacji (sposobu pisania programu, jakości kompilatora, szybkości procesora komputera,…). Oceniamy więc, co nie zależy od takich szczegółów, czyli ile czasu zajmuje uruchomienie algorytmu, gdy dostarczymy mu większe dane wejściowe. I zależy nam przede wszystkim na tym, kiedy możemy być pewni, że program został ukończony, dlatego zwykle chcemy wiedzieć, że zajmie to tak długo taki lub mniej czas.O
Stwierdzenie, że algorytm ma czas działania dla rozmiaru wejściowego oznacza, że istnieje pewna stała tak że algorytm wykonuje się co najwyżej w krokach , tj. Czas działania algorytmu rośnie co najwyżej tak szybko, jak (do współczynnika skalowania). Odnotowanie czasu działania algorytmu dla wielkości wejściowej , nieformalnie oznacza, że do pewnego współczynnika skalowania.n K KO(f(n)) n K f T ( n ) n O ( n ) T ( n ) ≤ f ( n )Kf(n) f T(n) n O(n) T(n)≤f(n)
Dolna granica
Czasami przydaje się mieć więcej informacji niż górna granica. jest odwrotnością : wyraża, że funkcja rośnie co najmniej tak szybko, jak inna. oznacza, że dla pewnego stałego , lub mówiąc nieformalnie, górę do pewnego współczynnika skalowania.Ω O T(n)=Ω(g(n)) T(N)≥K′g(n) K′ T(n)≥g(n)
Kiedy czas działania algorytmu można precyzyjnie określić, łączy i : wyraża to, że znane jest tempo wzrostu funkcji, aż do współczynnika skalowania. oznacza, że dla niektórych stałych i . Mówiąc nieformalnie, do pewnego współczynnika skalowania.Θ O Ω T(n)=Θ(h(n)) Kh(n)≥T(n)≥K′h(n) K K′ T(n)≈h(n)
Dalsze uwagi
„Małe” i są używane znacznie rzadziej w analizie złożoności. Mała jest silniejsza niż duża ; gdzie oznacza wzrost, który nie jest szybszy, oznacza, że wzrost jest ściśle wolniejszy. I odwrotnie, wskazuje na zdecydowanie szybszy wzrost.o ω o O O o ω
Byłem nieco nieformalny w powyższej dyskusji. Wikipedia ma formalne definicje i bardziej matematyczne podejście.
Należy pamiętać, że użycie znaku równości w i tym podobne jest błędne. Ściśle mówiąc, jest zbiorem funkcji zmiennej i powinniśmy pisać .T(n)=O(f(n)) O(f(n)) n T∈O(f)
Przykład: niektóre algorytmy sortowania
Ponieważ jest to raczej suche, dam przykład. Większość algorytmów sortowania ma kwadratowy najgorszy czas działania, tj. Dla danych wejściowych o rozmiarze czas działania algorytmu wynosi . Na przykład sortowanie selekcji ma czas działania , ponieważ wybranie tego elementu wymaga porównań , co daje łącznie porównania . W rzeczywistości liczba porównań wynosi zawsze dokładnie , co rośnie jako . Możemy więc dokładniej określić złożoność czasową sortowania selekcji: jest to .n O(n2) O(n2) k n−k n(n−1)/2 n(n−1)/2 n2 Θ(n2)
Teraz weź sortowanie korespondencji seryjnej . Sortowanie po scaleniu jest również kwadratowe ( ). To prawda, ale niezbyt precyzyjna. W rzeczywistości sortowanie korespondencji ma w najgorszym przypadku czas działania . Podobnie jak sortowanie selekcyjne, przepływ pracy sortowania scalającego jest zasadniczo niezależny od kształtu danych wejściowych, a jego czas działania wynosi zawsze do stałego mnożnika, tzn. Jest to .O(n2) O(nlg(n)) nlg(n) Θ(nlg(n))
Następnie rozważ szybkie sortowanie . Quicksort jest bardziej złożony. Z pewnością jest to . Co więcej, najgorszy przypadek szybkiego sortowania jest kwadratowy: najgorszym przypadkiem jest . Jednak najlepszy przypadek szybkiego sortowania (gdy dane wejściowe są już posortowane) ma charakter liniowy: najlepsze, co możemy powiedzieć dla dolnej granicy szybkiego segmentu w ogóle, to . Nie powtórzę tutaj dowodu, ale średnia złożoność quicksort (średnia przejęta przez wszystkie możliwe kombinacje danych wejściowych) wynosi .O(n2) Θ(n2) Ω(n) Θ(nlg(n))
Istnieją ogólne wyniki dotyczące złożoności algorytmów sortowania w typowych ustawieniach. Załóżmy, że algorytm sortowania może porównywać tylko dwa elementy jednocześnie, z wynikiem tak lub nie ( lub ). Jest zatem oczywiste, że czas działania dowolnego algorytmu sortującego to zawsze (gdzie jest liczbą elementów do posortowania), ponieważ algorytm musi przynajmniej raz porównać każdy element, aby wiedzieć, gdzie będzie pasował. Ta dolna granica może być spełniona, na przykład, jeśli dane wejściowe są już posortowane, a algorytm po prostu porównuje każdy element z następnym i utrzymuje je w porządku (to porównania ). Mniej oczywiste jest to, że maksymalny czas działania jest koniecznyx≤y x>y Ω(n) n n−1 Ω(nlg(n)) . Możliwe jest, że algorytm będzie czasem dokonywał mniej porównań, ale musi istnieć pewna stała tak że dla dowolnego rozmiaru wejściowego istnieje co najmniej jedno wejście, na którym algorytm daje więcej niż porównania. Ideą dowodu jest zbudowanie drzewa decyzyjnego algorytmu, tj. Śledzenie decyzji algorytmu na podstawie wyników każdego porównania. Ponieważ każde porównanie zwraca wynik „tak lub nie”, drzewo decyzyjne jest drzewem binarnym. Jestmożliwe permutacje danych wejściowych, a algorytm musi rozróżnić je wszystkie, więc wielkość drzewa decyzyjnego wynosiK n Knlg(n) n! n! . Ponieważ drzewo jest drzewem binarnym, do dopasowania wszystkich tych węzłów potrzeba . Głębokość to maksymalna liczba decyzji podejmowanych przez algorytm, więc uruchomienie algorytmu obejmuje co najmniej tyle porównań: maksymalny czas działania wynosi .Θ(lg(n!))=Θ(nlg(n)) Ω(nlg(n))
¹ Lub inne zużycie zasobów, takie jak miejsce w pamięci. W tej odpowiedzi rozważam tylko czas działania.
źródło
Zazwyczaj służy do określania górnych granic (oszacowanie z góry), podczas gdy służy do określania dolnych granic (oszacowanie z dołu), a jest używany, gdy pasują, w takim przypadku możesz użyć zamiast nich (zwykle), aby podać wynik.O Ω Θ Θ
źródło