Teorin om beräkningskomplexitet är en del av datavetenskapen. Den beskriver hur mycket tid (antal operationer) och hur mycket minne (lagringsutrymme) en algoritm kräver när problemstorleken växer. När man analyserar algoritmer försöker man ofta ta reda på hur resursåtgången beror på indatans storlek n, och jämföra olika algoritmer oberoende av maskin- eller implementationdetaljer. I praktiken finns ofta en avvägning mellan tid och minne: en algoritm som använder mindre tid kan behöva mer minne och vice versa.

Tidskomplexitet — grundbegrepp

Tidskomplexitet uttrycks vanligen med asymptotisk notation, där de vanligaste är Big O (övre gräns), Θ (tätt bound) och Ω (nedre gräns). Man fokuserar oftast på hur antalet element n påverkar antalet grundoperationer när n blir stort.

  • Konstant tid O(1): tiden förändras inte med n (t.ex. återvänd första elementet i en array).
  • Logaritmisk tid O(log n): t.ex. binärsökning i en sorterad lista.
  • Linjär tid O(n): t.ex. enkel genomsökning av en lista.
  • n log n O(n log n): många effektiva sorteringsalgoritmer (merge sort, heapsort).
  • Kvadratisk tid O(n²): enkla sorteringsmetoder som bubbelsort eller insertion sort i värsta fallet.
  • Exponential/ fakultet O(2^n), O(n!): uppstår i brute-force-sökningar av kombinationer (t.ex. vissa backtracking-problem).

Minneskomplexitet

Minneskomplexiteten (space complexity) anger hur mycket extra minne en algoritm behöver utöver indata. Den kan delas i auxiliärt minne (extra arbetsminne) och totalt minne (inklusive indata). Exempelvis använder merge sort O(n) extra minne medan quicksort ofta använder O(log n) stackminne i genomsnitt.

Bästa-, genomsnitts- och sämsta-fall

Vid analys skiljer man mellan:

  • Bästafall — snabbaste möjliga körning för någon indatakonfiguration.
  • Genomsnittfall — förväntad körning för en sannolikhetsfördelning av indatan.
  • Sämstafall — garanti för att algoritmen aldrig blir långsammare än detta.

Sämstafallskomplexitet används ofta för att ge robusta garantier, medan genomsnittfall kan beskriva praktisk prestanda bättre om indatan är slumpmässig eller typisk.

Komplexitetsklasser och svårighetsgrad för problem

Komplexitetsteorin grupperar problem efter hur svåra de är att lösa eller verifiera:

  • P — problem som kan lösas i polynomtid (effektiva algoritmer finns).
  • NP — beslutproblem där en lösning kan verifieras i polynomtid.
  • NP-komplett — de svåraste problemen i NP; om något NP-komplett problem ligger i P följer att P = NP.
  • NP-hård — åtminstone lika svårt som NP-problem, men behöver inte vara i NP.

Dessa klasser hjälper att förstå när exakta lösningar är realistiska eller när man bör söka approximationer eller heuristiker.

Analysera algoritmer — vanliga metoder

  • Räkna elementära operationer som jämförelser eller tilldelningar och välj en modell (t.ex. RAM-modellen) för att bedöma kostnaden.
  • Använd rekurrensrelationer för algoritmer som delar upp problemet (divide and conquer) och lös dem med Masterteoremet eller substitutionsmetoden.
  • Amortiserad analys för datastrukturer där enstaka operationer kan vara dyra men genomsnittet över många operationer är billigt (t.ex. dynamiska arrayer).
  • Reduktioner för att visa att ett problem är minst så svårt som ett annat (används i bevis av NP-kompletthet).

Praktiska aspekter och begränsningar

Teoretisk komplexitet fångar asymptotiskt beteende men säger inte allt om praktisk prestanda. Några viktiga punkter:

  • Konstantfaktorer och låga ordningens termer kan avgöra vad som är snabbast för realistiska n.
  • Hur indata är representerad (t.ex. antal bitar) påverkar beräkningen; bitkomplexitet kan skilja sig från värdebaserad komplexitet.
  • Cache, parallellism och moderna processorarkitekturer kan påverka vilka algoritmer som är bäst i praktiken.
  • När exakta lösningar är för dyra används ofta heuristiska metoder, approximationer eller parametriserade algoritmer.

Summering

Beräkningskomplexitet ger ett språk och verktyg för att beskriva och jämföra hur dyra algoritmer är i tid och minne. Genom att analysera asymptotiskt beteende, känna till vanliga komplexitetsklasser och använda lämpliga analysmetoder kan man välja eller designa algoritmer som är lämpliga både teoretiskt och praktiskt för ett givet problem och tillämpningsområde.