logo

Big O Notation Tutorial – En guide til Big O-analyse

Stor O notation er et kraftfuldt værktøj, der bruges i datalogi til at beskrive tidskompleksiteten eller rumkompleksiteten af ​​algoritmer. Det giver en standardiseret måde at sammenligne effektiviteten af ​​forskellige algoritmer med hensyn til deres værst tænkelige ydeevne. Forståelse Stor O notation er afgørende for at analysere og designe effektive algoritmer.

I denne tutorial vil vi dække det grundlæggende i Stor O notation , dens betydning, og hvordan man analyserer kompleksiteten af ​​algoritmer ved hjælp af Store O .



Indholdsfortegnelse

Hvad er Big-O-notation?

Big-O , almindeligvis omtalt som Rækkefølge af , er en måde at udtrykke det på øvre grænse af en algoritmes tidskompleksitet, da den analyserer værste tilfælde algoritmens situation. Det giver en Øverste grænse på den tid, en algoritme tager i forhold til størrelsen af ​​input. Det er betegnet som O(f(n)) , hvor f(n) er en funktion, der repræsenterer antallet af operationer (trin), som en algoritme udfører for at løse et problem af størrelse n .



Big-O notation bruges til at beskrive ydeevnen eller kompleksiteten af ​​en algoritme. Konkret beskriver den værste tilfælde med hensyn til tid eller rummets kompleksitet.

Vigtigt punkt:

  • Stor O notation beskriver kun en funktions asymptotiske adfærd, ikke dens nøjagtige værdi.
  • Det Stor O notation kan bruges til at sammenligne effektiviteten af ​​forskellige algoritmer eller datastrukturer.

Definition af Big-O notation:

Givet to funktioner f(n) og g(n) , det siger vi f(n) er O(g(n)) hvis der findes konstanter c> 0 og n 0 >= 0 sådan f(n) <= c*g(n) for alle n>= n 0 .



I enklere vendinger, f(n) er O(g(n)) hvis f(n) vokser ikke hurtigere end c*g(n) for alle n>= n0hvor c og n0er konstanter.

Hvorfor er Big O-notation vigtig?

Big O-notation er en matematisk notation, der bruges til at beskrive den værste tidskompleksitet eller effektiviteten af ​​en algoritme eller den værst tænkelige pladskompleksitet af en datastruktur. Det giver en måde at sammenligne ydeevnen af ​​forskellige algoritmer og datastrukturer og til at forudsige, hvordan de vil opføre sig, når inputstørrelsen øges.

Big O-notation er vigtig af flere grunde:

  • Big O-notation er vigtig, fordi den hjælper med at analysere effektiviteten af ​​algoritmer.
  • Det giver en måde at beskrive, hvordan køretid eller pladsbehov af en algoritme vokser, efterhånden som inputstørrelsen øges.
  • Giver programmører mulighed for at sammenligne forskellige algoritmer og vælge den mest effektive til et specifikt problem.
  • Hjælper med at forstå skalerbarheden af ​​algoritmer og forudsige, hvordan de vil fungere, efterhånden som inputstørrelsen vokser.
  • Gør det muligt for udviklere at optimere kode og forbedre den samlede ydeevne.

Egenskaber ved Big O-notation:

Nedenfor er nogle vigtige egenskaber ved Big O-notation:

1. Refleksivitet:

For enhver funktion f(n), f(n) = O(f(n)).

Eksempel:

escape karakter java

f(n) = n2, så f(n) = O(n2).

2. Transitivitet:

Hvis f(n) = O(g(n)) og g(n) = O(h(n)), så er f(n) = O(h(n)).

Eksempel:

f(n) = n3, g(n) = n2, h(n) = n4. Så f(n) = O(g(n)) og g(n) = O(h(n)). Derfor er f(n) = O(h(n)).

3. Konstant faktor:

For enhver konstant c> 0 og funktioner f(n) og g(n), hvis f(n) = O(g(n)), så cf(n) = O(g(n)).

Eksempel:

java while loop

f(n) = n, g(n) = n2. Så f(n) = O(g(n)). Derfor er 2f(n) = O(g(n)).

4. Sumregel:

Hvis f(n) = O(g(n)) og h(n) = O(g(n)), så er f(n) + h(n) = O(g(n)).

Eksempel:

f(n) = n2, g(n) = n3, h(n) = n4. Så er f(n) = O(g(n)) og h(n) = O(g(n)). Derfor er f(n) + h(n) = O(g(n)).

5. Produktregel:

Hvis f(n) = O(g(n)) og h(n) = O(k(n)), så f(n) * h(n) = O(g(n) * k(n)) .

Eksempel:

f(n) = n, g(n) = n2, h(n) = n3, k(n) = n4. Så f(n) = O(g(n)) og h(n) = O(k(n)). Derfor f(n) * h(n) = O(g(n) * k(n)) = O(n5).

6. Sammensætningsregel:

Hvis f(n) = O(g(n)) og g(n) = O(h(n)), så er f(g(n)) = O(h(n)).

Eksempel:

f(n) = n2, g(n) = n, h(n) = n3. Så f(n) = O(g(n)) og g(n) = O(h(n)). Derfor er f(g(n)) = O(h(n)) = O(n3).

Almindelige Big-O-notationer:

Big-O notation er en måde at måle kompleksiteten af ​​tid og rum i en algoritme. Den beskriver den øvre grænse for kompleksiteten i det værste tilfælde. Lad os se nærmere på de forskellige typer tidskompleksiteter:

1. Lineær tidskompleksitet: Stor O(n) kompleksitet

Lineær tidskompleksitet betyder, at køretiden for en algoritme vokser lineært med størrelsen af ​​input.

Overvej for eksempel en algoritme, der går gennem en matrix for at finde et bestemt element :

Kodestykke
bool findElement(int arr[], int n, int key) {  for (int i = 0; i < n; i++) {  if (arr[i] == key) {  return true;  }  }  return false; }>

2. Logaritmisk tidskompleksitet: Stor O(log n) kompleksitet

Logaritmisk tidskompleksitet betyder, at køretiden for en algoritme er proportional med logaritmen af ​​inputstørrelsen.

For eksempel en binær søgealgoritme har en logaritmisk tidskompleksitet:

Kodestykke
int binarySearch(int arr[], int l, int r, int x) {  if (r>= l) {int mid = l + (r - l) / 2;  hvis (arr[mid] == x) returner midt;  if (arr[mid]> x) returner binærsøgning(arr, l, mid - 1, x);  return binarySearch(arr, mid + 1, r, x);  } returnere -1; }>

3. Kvadratisk tidskompleksitet: Stor O(n2) Kompleksitet

Kvadratisk tidskompleksitet betyder, at køretiden for en algoritme er proportional med kvadratet på inputstørrelsen.

For eksempel en simpel boblesorteringsalgoritme har en kvadratisk tidskompleksitet:

Kodestykke
void bubbleSort(int arr[], int n) {  for (int i = 0; i < n - 1; i++) {  for (int j = 0; j < n - i - 1; j++) {  if (arr[j]>arr[j + 1]) { swap(&arr[j], &arr[j + 1]);  } } } }>

4. Kubiktidskompleksitet: Stor O(n3) Kompleksitet

Kubisk tidskompleksitet betyder, at køretiden for en algoritme er proportional med kuben af ​​inputstørrelsen.

For eksempel en naiv matrix multiplikationsalgoritme har en kubisk tidskompleksitet:

Kodestykke
void multiply(int mat1[][N], int mat2[][N], int res[][N]) {  for (int i = 0; i < N; i++) {  for (int j = 0; j < N; j++) {  res[i][j] = 0;  for (int k = 0; k < N; k++)  res[i][j] += mat1[i][k] * mat2[k][j];  }  } }>

5. Polynomisk tidskompleksitet: Stor O(nk) Kompleksitet

Polynomisk tidskompleksitet refererer til tidskompleksiteten af ​​en algoritme, der kan udtrykkes som en polynomiel funktion af inputstørrelsen n . I Big O notation, siges en algoritme at have polynomisk tidskompleksitet, hvis dens tidskompleksitet er k ) , hvor k er en konstant og repræsenterer graden af ​​polynomiet.

Algoritmer med polynomisk tidskompleksitet anses generelt for at være effektive, da køretiden vokser med en rimelig hastighed, når inputstørrelsen øges. Almindelige eksempler på algoritmer med polynomisk tidskompleksitet omfatter lineær tidskompleksitet O(n) , kvadratisk tidskompleksitet O(n 2 ) , og kubiktidskompleksitet O(n 3 ) .

6. Eksponentiel tidskompleksitet: Big O(2n) Kompleksitet

Eksponentiel tidskompleksitet betyder, at køretiden for en algoritme fordobles med hver tilføjelse til inputdatasættet.

For eksempel problemet med generere alle delmængder af et sæt er af eksponentiel tidskompleksitet:

Kodestykke
void generateSubsets(int arr[], int n) {  for (int i = 0; i < (1 << n); i++) {  for (int j = 0; j < n; j++) {  if (i & (1 << j)) {  cout << arr[j] << ' ';  }  }  cout << endl;  } }>

Faktoriel tidskompleksitet: Stor O(n!) kompleksitet

Faktoriel tidskompleksitet betyder, at køretiden for en algoritme vokser faktorielt med størrelsen af ​​inputtet. Dette ses ofte i algoritmer, der genererer alle permutationer af et sæt data.

Her er et eksempel på en faktoriel tidskompleksitetsalgoritme, som genererer alle permutationer af et array:

Kodestykke
void permute(int* a, int l, int r) {  if (l == r) {  for (int i = 0; i <= r; i++) {  cout << a[i] << ' ';  }  cout << endl;  }  else {  for (int i = l; i <= r; i++) {  swap(a[l], a[i]);  permute(a, l + 1, r);  swap(a[l], a[i]); // backtrack  }  } }>

Hvis vi plotter de mest almindelige Big O-notationseksempler, ville vi have en graf som denne:

asymtotisk-analyse

Hvordan bestemmer man Big O-notation?

Stor O notation er en matematisk notation, der bruges til at beskrive asymptotisk adfærd af en funktion, efterhånden som dens input bliver uendeligt stor. Det giver en måde at karakterisere effektiviteten af ​​algoritmer og datastrukturer.

forskel i python

Trin til at bestemme Big O-notation:

1. Identificer det dominerende udtryk:

  • Undersøg funktionen og identificer udtrykket med den højeste vækstorden, når inputstørrelsen øges.
  • Ignorer eventuelle konstante faktorer eller termer af lavere orden.

2. Bestem vækstrækkefølgen:

  • Vækstrækkefølgen af ​​det dominerende udtryk bestemmer Big O-notationen.

3. Skriv Big O-notationen:

  • Big O-notationen skrives som O(f(n)), hvor f(n) repræsenterer det dominerende led.
  • For eksempel, hvis det dominerende led er n^2, vil Big O-notationen være O(n^2).

4. Forenkle notationen (valgfrit):

  • I nogle tilfælde Big O branding n kan forenkles ved at fjerne konstante faktorer eller ved at bruge en mere kortfattet notation.
  • For eksempel, O(2n) kan forenkles til På).

Eksempel:

Funktion: f(n) = 3n3+ 2n2+ 5n + 1

  1. Dominerende term: 3n3
  2. Vækstorden: Kubisk (n3)
  3. Big O-notation: O(n3)
  4. Forenklet notation: O(n3)

Matematiske eksempler på runtime-analyse:

Nedenstående tabel illustrerer runtime-analysen af ​​forskellige rækkefølger af algoritmer, når inputstørrelsen (n) øges.

nlog(n)nn * log(n)n^22^nn!
101101010010243628800
tyve2.996tyve59,940010485762.432902e+1818

Algoritmiske eksempler på runtime-analyse:

Nedenstående tabel kategoriserer algoritmer baseret på deres runtime kompleksitet og giver eksempler for hver type.

TypeNotationEksempel algoritmer
LogaritmiskO(log n)Binær søgning
LineærPå)Lineær søgning
SuperlineærO(n log n)Heap Sort, Merge Sort
PolynomiumO(n^c)Strassens matrixmultiplikation, boblesortering, udvælgelsessortering, indsættelsessortering, spandsortering
EksponentielO(c^n)Hanois tårn
FaktorielPå!)Determinant udvidelse af mindreårige, Brute force Søgealgoritme for Traveling Salesman Problem

Algoritmeklasser med antal operationer og udførelsestid:

Nedenfor er klasserne af algoritmer og deres eksekveringstider på en computer, der udfører 1 million operationer pr. sekund (1 sek = 10 6 μsek = 10 3 msek) :

Store O-notationsklasser

f(n)

Big O-analyse (antal operationer) for n = 10

Udførelsestid (1 instruktion/μsek)

konstant

O(1)

1

1 μsek

logaritmisk

O(logn)

3,32

3 μsek

lineær

På)

10

10 μsek

boblesorteringspython

O(nlogn)

O(nlogn)

33,2

33 μsek

kvadratisk

2)

102

100 μsek

kubik

3)

103

1 msek

eksponentiel

O(2n)

1024

10 msek

css ombryd tekst

faktorielle

På!)

10!

3,6288 sek

Sammenligning af Big O notation, Big Ω (Omega) notation og Big θ (Theta) notation:

Nedenfor er en tabel, der sammenligner Big O notation, Ω (Omega) notation og θ (Theta) notation:

NotationDefinitionForklaring
Big O (O)f(n) ≤ C * g(n) for alle n ≥ n0Beskriver den øvre grænse for algoritmens køretid i værste tilfælde .
Ω (Omega)f(n) ≥ C * g(n) for alle n ≥ n0Beskriver den nedre grænse for algoritmens køretid i bedste tilfælde .
θ (Theta)C1* g(n) ≤ f(n) ≤ C2* g(n) for n ≥ n0Beskriver både de øvre og nedre grænser for algoritmens løbe tid .

I hver notation:

  • f(n) repræsenterer den funktion, der analyseres, typisk algoritmens tidskompleksitet.
  • g(n) repræsenterer en specifik funktion, der afgrænser f(n) .
  • C, C1, og C2 er konstanter.
  • n 0 er den mindste inputstørrelse, udover hvilken uligheden gælder.

Disse notationer bruges til at analysere algoritmer baseret på deres worst case (Big O) , bedste tilfælde (Ω) , og gennemsnit-case (θ) scenarier.

Ofte stillede spørgsmål om Big O-notation:

Spørgsmål 1. Hvad er Big O-notation?

Svar: Big O Notation er en matematisk notation, der bruges til at beskrive den øvre grænse for en algoritmes tidskompleksitet i forhold til, hvordan den vokser i forhold til størrelsen af ​​input.

Spørgsmål 2. Hvorfor er Big O-notation vigtig?

Svar: Det hjælper os med at analysere og sammenligne effektiviteten af ​​algoritmer ved at fokusere på det værst tænkelige scenarie og forstå, hvordan deres ydeevne skalerer med inputstørrelse.

Spørgsmål 3. Hvordan beregnes Big O Notation?

Svar: Big O Notation bestemmes ved at identificere den dominerende operation i en algoritme og udtrykke dens tidskompleksitet i form af n, hvor n repræsenterer inputstørrelsen.

Spørgsmål 4. Hvad betyder O(1) i Big O-notation?

Svar: O(1) angiver konstant tidskompleksitet, hvilket indikerer, at en algoritmes eksekveringstid ikke ændres uanset inputstørrelsen.

Spørgsmål 5. Hvad er betydningen af ​​forskellige Big O-kompleksiteter som O(log n) eller O(n^2)?

Svar: Forskellige kompleksiteter som O(log n) eller O(n^2) repræsenterer, hvordan en algoritmes ydeevne skaleres, når inputstørrelsen øges, hvilket giver indsigt i dens effektivitet og skalerbarhed.

Spørgsmål 6. Kan Big O-notation også anvendes på rumkompleksitet?

Svar: Ja, Big O Notation kan også bruges til at analysere og beskrive en algoritmes rumkompleksitet, hvilket angiver, hvor meget hukommelse den kræver i forhold til inputstørrelsen.

Relateret artikel: