Algorytmiczna intuicja dla złożoności logarytmicznej

59

Wydaje mi się, że mam rozsądne pojęcie o złożoności takiej jak , Θ ( n ) i Θ ( n 2 ) .O(1)Θ(n)Θ(n2)

Jeśli chodzi o listę, to ciągłe wyszukiwanie, więc po prostu dostaje się na czele listy. Θ ( n ) , gdzie będę chodzić całą listę, a Θ ( n 2 ) idzie listę raz dla każdego elementu listy.O(1)Θ(n)Θ(n2)

Czy istnieje podobny intuicyjny sposób uchwycenia inny niż po prostu wiedza, że ​​leży gdzieś pomiędzy O ( 1 ) a Θ ( n ) ?Θ(logn)O(1)Θ(n)

Chanzor
źródło
8
log n oznacza „wyszukiwanie”: pomyśl wyszukiwanie binarne
Suresh
2
Użycie celu zadania tego pytania jest nieprawidłowe, ponieważ oznacza ono jedynie górną granicę. Na przykład stały czas to O ( log n ) . θ byłby bardziej odpowiedni. Zobacz meta pytanie: meta.cs.stackexchange.com/questions/182/…OO(logn)θ
Aryabhata
1
Więcej informacji na temat SO: co dokładnie oznacza ? O(logn).
Ran G.
Mała uwaga: w klasycznych ustawieniach maszyny Turinga wszystkie algorytmy mają wartość , ponieważ muszą czytać każdy symbol wejścia co najmniej raz. Wyszukiwanie binarne można przeprowadzić w O ( log n ), ponieważ mamy obietnicę, że na przykład lista jest posortowana. Ω(n)O(logn)
chazisop
1
Późny wkład: z definicji podstawowy logarytm liczby n jest tylko liczbą pomnożeń b przez siebie, aby uzyskać n . b l = nbnbn . Na przykład 2 3 = 8bl=nl=logb(n) . Więc jeśli masz numer n i chcesz dowiedzieć się, co l o, g , b ( n ) = ? po prostu dziel go przez b, aż osiągniesz 1 (zakładając, że n to potęga b dla uproszczenia). Liczba przegród jest równy L O g b ( n ) . Algorytmy takie zachowanie podziału mają czasy pracy w O ( L O g23=8log2(8)=3nlogb(n)=?b1nblogb(n) . O(log(n))
saadtaame

Odpowiedzi:

53

złożony jest zwykle połączony z podziału. Korzystając z list jako przykładu, wyobraź sobie listę, której elementy są posortowane. Możesz przeszukiwać tę listę w czasie O ( log n ) - tak naprawdę nie musisz patrzeć na każdy element ze względu na posortowany charakter listy.Θ(logn)O(logn)

Jeśli spojrzysz na element na środku listy i porównasz go z elementem, którego szukasz, możesz od razu powiedzieć, czy leży on w lewej czy prawej połowie tablicy. Następnie możesz wziąć tę połowę i powtórzyć procedurę, aż znajdziesz ją lub dojdziesz do listy z 1 przedmiotem, który trywialnie porównujesz.

Widać, że lista skutecznie zmniejsza o połowę każdy krok. Oznacza to, że jeśli otrzymasz listę o długości , maksymalna liczba kroków, które musisz osiągnąć, aby dotrzeć do listy jednego elementu, to 5 . Jeśli masz listę 128 = 2 7 elementów, potrzebujesz tylko 7 kroków, dla listy 1024 = 2 10 potrzebujesz tylko 10 kroków itp.325128=2771024=21010

Jak widać, wykładnik w 2 n zawsze pokazuje liczbę kroków potrzebnych. Logarytm służy do „wyodrębnienia” dokładnie tej liczby wykładniczej, na przykład log 2 2 10 = 10 . Uogólnia również, aby wyświetlać długości, które nie są potęgami dwóch długości.n2nlog2210=10

Karel Petranek
źródło
4
Należy zauważyć, że dzieje się tak tylko O(log n)wtedy, gdy lista ma stały dostęp losowy w czasie. W przypadku bardziej typowych implementacji list (list połączonych) jest toO(n log n)
asm
1
Wyszukiwanie binarne nie działa na listach z powodu braku wskaźników; zwykle odbywa się to na tablicach.
Raphael
Wyszukiwanie binarne działa dobrze na listach. Jest to po prostu dość bezcelowe, ponieważ jest o wiele bardziej skomplikowane niż wymagane / przydatne / praktyczne.
Anton
@AndrewMyers Przeszukiwanie połączonej listy jest dokładniejsze O(n)
phant0m 30.09.12
1
@ phant0m Tak, zajęło mi trochę, aby zrozumieć, że zakładasz, że ruszasz się z bieżącej pozycji zamiast przemierzać od początku za każdym razem.
asm
38

W kategoriach (zrównoważonych) drzew (powiedzmy, drzewa binarnego, więc wszystkie są podstawą 2):log

  • pobiera korzeń drzewaΘ(1)
  • to przejście od korzenia do liściaΘ(logn)
  • przemierza wszystkie węzły drzewaΘ(n)
  • to działania na wszystkich podzbiorach dwóch węzłów w drzewie, np. Liczba różnych ścieżek między dowolnymi dwoma węzłami.Θ(n2))
  • - uogólnienie powyższego dla dowolnego podzbioru k węzłów (dla stałej k )Θ(nk)kk
  • jest działaniem na wszystkie możliwe podzbiory węzłów (podzbiory wszystkich możliwych rozmiarów, tj. K = 1 , 2 , , n .). Na przykład liczba różnychpoddrzewadrzewa.Θ(2)n)k=1,2),,n
Ran G.
źródło
5
Aby dodać do tego, intuicja dla pochodzi z dwóch rzeczy: 1.) Nawrót T ( n ) = T ( Θ(loglogn)i 2.) Wyszukiwanie binarne czegoś wielkościlog(n),tj. wyszukiwanie binarne na wysokości drzewa. T(n)=T((n))+1log(n)
mcorley,
17

Aby było możliwe, musisz być w stanie zmniejszyć rozmiar problemu proporcjonalnie o pewną dowolną wartość w stosunku do n przy stałej operacji czasu.O(logn)n

Na przykład w przypadku wyszukiwania binarnego można zmniejszyć rozmiar problemu o połowę przy każdej operacji porównania.

Czy musisz teraz zmniejszyć problem o połowę, a właściwie nie. Algorytmem jest nawet jeśli może on zmniejszyć przestrzeń wyszukiwania problemów o 0,0001%, o ile procent i operacja, której używa do zmniejszenia rozmiaru problemu, pozostaje stała, jest to algorytm O ( log n ) , nie będzie to szybki algorytm, ale nadal jest to O ( log n ) z bardzo dużą stałą. (Zakładając, że mówimy o log n z logiem base 2)O(logn)O(logn)O(logn)logn

Ken Li
źródło
1
Co by było, gdyby „obniżka kwoty” nie była stała?
Svish
@Svish Jeśli możesz zmniejszyć problem w dodatnim tempie, nadal byłby to algorytm , chociaż prawdopodobnie nie byłby już ściśle związany. Trudno powiedzieć o stopie ujemnej. Założono, że w tym przypadku odpowiedź jest raczej prosta, ponieważ pytanie to ma swoją zaletę, z przyjemnością zadajesz je jako pytanie samo w sobie. O(logn)
Ken Li
Tak, miałem na myśli, że przestrzeń wyszukiwania problemów zawsze zmniejszała się, ale niekoniecznie ze stałą szybkością. Właśnie myślałem o twoim „tak długo, jak procent i operacja używana do zmniejszenia rozmiaru problemu pozostaje stała, jest to algorytm O (log n)”; gdyby miał inną nazwę, jeśli procent nie był stały.
Svish
8

Pomyśl o algorytmie konwertującym liczbę dziesiętną na binarnąn

while n != 0:
   print n%2, 
   n = n/2

Ta whilepętla uruchamia razy.log(n)

Pratik Deoghare
źródło
1
Z pewnością ten program zapętla razy, ale ogólnie mówiąc, gdy mówimy o złożoności O ( f ( s ) ) , s jest wielkością twojego wejścia. Tutaj rozmiar twojego wejścia to już s = log n , więc powiedziałbym, że ten program jest tylko liniowy (w O ( s ) )lognO(fa(s))ss=lognO(s)
jmad
@jmad Right. Ale ten przykład daje intuicję w log (n).
Pratik Deoghare
@jmad Mógłbym również użyć algorytmu do generowania liczb losowych, ale chciałem, żeby było to tak proste, jak to możliwe.
Pratik Deoghare
8

Tak, jest między 1 a n , ale jest bliższy 1 niż n . Co to jest log ( n ) ? Funkcja log jest odwrotną funkcją potęgowania. Zacznę od potęgowania, a powinieneś lepiej zrozumieć, czym jest logarytm.log(n)1n1nlog(n)

Rozważ dwie liczby, i 2 100 . 2 100 to 2 pomnożone ze sobą 100 razy. Możesz z pewnym wysiłkiem policzyć 100 liczb, ale czy możesz policzyć 2 100 ? Założę się, że nie możesz. Dlaczego? 2 100 to tak duża liczba, że ​​jest większa niż liczba wszystkich atomów we wszechświecie. Zastanów się przez chwilę. Jest to tak duża liczba, że ​​pozwala nadać każdemu atomowi nazwę (liczbę). A liczba atomów w twoim paznokciu jest prawdopodobnie rzędu miliardów. 2 100 powinno wystarczyć dla każdego (gra słów :).1002)1002)1002)1001002)1002)1002)100

Teraz między dwiema liczbami, i 2 100 , 100 jest logarytmem 2 100 (w bazie 2 ). 100 to stosunkowo niewielka liczba niż 2 100 . Każdy powinien mieć w domu 100 różnych przedmiotów. Ale 2 100 jest wystarczające dla wszechświata. Myśl o domu a wszechświecie, myśląc o log ( n ) i n .1002)1001002)1002)1002)1001002)100log(n)n

Skąd się bierze potęgowanie i logarytmy? Dlaczego tak bardzo interesują się informatyką? Możesz tego nie zauważyć, ale potęgowanie jest wszędzie. Czy zapłaciłeś odsetki od karty kredytowej? Właśnie zapłaciłeś wszechświatowi za swój dom (nie tak źle, ale krzywa pasuje). Lubię myśleć, że potęgowanie wynika z reguły produktu, ale inni mogą podać więcej przykładów. Jaką zasadę produktu możesz zapytać; I odpowiem.

Załóżmy, że masz dwa miasta i B , a są między nimi dwa sposoby. Jaka jest liczba ścieżek między nimi? Dwa. To jest banalne. Powiedzmy teraz, że istnieje inne miasto C i możesz przejść z B do C na trzy sposoby. Ile jest teraz ścieżek między A i C ? Sześć, prawda? Jak to zdobyłeś? Policzyłeś je? A może ich pomnożyłeś? Tak czy inaczej, łatwo zauważyć, że oba sposoby dają podobny wynik. Teraz, jeśli dodasz miasto D, do którego można dotrzeć z C na cztery sposoby, ile jest dróg między A i D.ZAbdobdoZAdoredoZAre? Policz, jeśli mi nie ufasz, ale równa się czyli 24 . Teraz, jeśli jest dziesięć miast i są dwie ścieżki z jednego miasta do drugiego, i są ułożone tak, jakby były na linii prostej. Ile jest ścieżek od początku do końca? Pomnóż je, jeśli mi nie ufasz, ale powiem ci, że są 2 10 , czyli 1024 . Zobacz, że 2 10 jest wykładniczym wynikiem 10 , a 10 jest logarytmem 2 10 . 10 to mała liczba w porównaniu do 1024 .2)3)4242)1010242)1010102)10101024

Funkcja logarytm jest n co n jest 2 n (zauważ, że 2 jest podstawa logarytmu jest). Jeśli zwielokrotnisz log b ( n ) ze sobą b razy (zauważ, że b jest podstawą logarytmu), otrzymasz n . log ( n ) jest tak mały, tak mały w porównaniu z n , że jest wielkości twojego domu, gdzie n jest wielkością wszechświata.log2)(n)nn2)n2)logb(n)bbnlog(n)nn

Praktycznie rzecz biorąc, funkcje działają bardzo podobnie do funkcji stałych. Rosną z n , ale rosną bardzo powoli. Jeśli zoptymalizowałeś program do działania w czasie logarytmicznym, który zajmował dzień wcześniej, prawdopodobnie uruchomisz go w kolejności minut. Sprawdź sam problemy z Project Euler.log(n)n

Ravi
źródło
3
Chociaż dobrze napisana, odpowiedź ta nie zawiera prawie żadnych informacji poza „ jest naprawdę mały”. log(n)
Raphael
3
Próbowałem podać intuicję, jak mały jest.
Ravi
5

Aby kontynuować Twój motyw, jest jak wielokrotne zgadywanie gdzie x znajduje się na liście i mówienie „wyżej” lub „niżej” (pod względem indeksu).O(logn)x

Nadal opiera się na wielkości listy, ale wystarczy odwiedzić tylko ułamek elementów.

dpatchery
źródło
4

Jeśli mamy algorytm dzielenia i zdobywania i wykonujemy tylko jedno rekurencyjne wywołanie podproblemu, a jest to drugi przypadek w twierdzeniu Master , tzn. Złożoność czasowa części nierekurencyjnej wynosi , wówczas złożoność algorytmu wyniesie Θ ( lg k + 1 n ) .Θ(lgkn)Θ(lgk+1n)

Innymi słowy, gdy mamy algorytm dziel i zwyciężaj z jednym wywołaniem rekurencyjnym do samego problemu z rozmiarem, stałym czynnikiem obecnego problemu, a czas w części nierekurencyjnej wynosi (stały), to czas działania algorytmu wyniesie lg n .Θ(1)lgn

Wyszukiwania binarnego algorytm jest klasycznym przykładem.

Kaveh
źródło
1

Intuicja mówi, ile razy można zmniejszyć liczbę o połowę, powiedzmy n, zanim zostanie zmniejszona do 1, to O (lg n).

Aby wizualizować, spróbuj narysować je jako drzewo binarne i policz liczbę poziomów, rozwiązując ten postęp geometryczny.

2^0+2^1+...+2^h = n
użytkownik1234
źródło
Witamy na stronie! To, co mówisz, jest oczywiście prawdą, ale nie rozumiem, co dodaje do istniejących odpowiedzi. Kilka odpowiedzi już mówi, że logarytm jest liczbą razy, którą możesz podzielić przez dwa, zanim trafisz 1, a odpowiedź Ran już mówi, że jest wysokością drzewa binarnego z n liści. lognn
David Richerby