Big-O-notation från grunden
Förstå varför asymptotisk tillväxt är viktig, hur konstanter och termer av lägre ordning utelämnas och hur ni snabbt tolkar Big-O.
Big-O-notation från grunden är en gratis lektion i Förberedelse inför kodningsintervjuer på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Förberedelse inför kodningsintervjuer, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Förberedelse inför kodningsintervjuer innehåller totalt 4 lektioner.
Varför mäta algoritmers effektivitet
Två program kan båda vara korrekta, men det ena blir klart på ett ögonblick medan det andra körs i timmar. Tidskomplexitet beskriver hur körtiden växer när indata blir större.
# O(n) approach
def find_max_linear(nums):
m = nums[0]
for n in nums:
if n > m: m = n
return m
# O(n^2) approach (unnecessary double loop)
def find_max_quadratic(nums):
for i in range(len(nums)):
is_max = all(nums[i] >= nums[j] for j in range(len(nums)))
if is_max: return nums[i]
print(find_max_linear([3, 1, 4, 1, 5, 9])) # 9Big-O: asymptotisk övre gräns
Big-O beskriver den värsta fallens övre gräns för hur snabbt kostnaden växer. Tricket är att ta bort konstanter och mindre termer, eftersom bara den dominerande termen spelar roll i stor skala. Se koden.
# T(n) = 3n^2 + 5n + 100 is O(n^2)
# because the n^2 term dominates for large n
# T(n) = 2n + 1000 is O(n)
# the constant 1000 becomes negligible
# Rule: drop constants and lower-order terms
# 5n^3 + 2n^2 + n + 1 => O(n^3)
# 100 * log(n) + n => O(n)
print('O(n^2) example: counting iterations')
n = 1000
count = sum(1 for i in range(n) for j in range(n))
print(count) # 1_000_000 = n^2Vanliga komplexitetsklasser
Från snabbast till långsammast: O(1), O(log n), O(n), O(n log n), O(n^2), O(2^n), O(n!). Om ni känner till dessa kan ni välja rätt metod innan ni skriver en enda rad.
import math
n = 1000
print(f'O(1): {1}')
print(f'O(log n): {int(math.log2(n))}')
print(f'O(n): {n}')
print(f'O(n log n): {int(n * math.log2(n))}')
print(f'O(n^2): {n**2}')
# O(2^n) for n=1000 is astronomically large
# O(n!) even largerAtt utelämna konstanter: varför det är viktigt
Att köra 5n steg eller 2n steg ger i båda fallen O(n) — konstanter beror på hårdvaran, inte algoritmen. Big-O utelämnar dem så att du kan jämföra skalningen på samma villkor.
# Both are O(n) — different constants
def count_a(n):
total = 0
for i in range(n): # n ops
total += 1
for i in range(n): # n ops
total += 1
return total # T(n) = 2n => O(n)
def count_b(n):
total = 0
for i in range(5 * n): # 5n ops
total += 1
return total # T(n) = 5n => O(n)
print(count_a(10), count_b(10)) # 20 50Bästa, genomsnittliga och värsta fall
Big-O beskriver värsta fallet; Omega beskriver det bästa fallet; Theta är en snäv gräns för båda. När en intervjuare frågar efter "komplexiteten" menar de nästan alltid värsta fallet.
def linear_search(nums, target):
for i, n in enumerate(nums):
if n == target:
return i # best case: target at index 0 => O(1)
return -1 # worst case: not found => O(n)
# Best case O(1): target is first element
print(linear_search([5,1,2,3], 5)) # 0
# Worst case O(n): target not in list
print(linear_search([1,2,3,4], 9)) # -1O(log n): halvera sökutrymmet
En algoritm är O(log n) när den halverar indata i varje steg, som vid binärsökning. Även för en miljard element behövs bara omkring 30 steg — otroligt snabbt. Se koden.
def binary_search(arr, target):
lo, hi = 0, len(arr) - 1
steps = 0
while lo <= hi:
steps += 1
mid = (lo + hi) // 2
if arr[mid] == target:
return mid, steps
elif arr[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1, steps
import math
arr = list(range(1000))
idx, s = binary_search(arr, 999)
print(f'Found at {idx} in {s} steps (log2(1000)~={math.log2(1000):.1f})')O(n log n): undre gränsen för sortering
Varje jämförelsebaserad sortering behöver minst O(n log n) i värsta fallet — det är en verklig matematisk undre gräns. Därför har sortera-och-skanna totalt komplexiteten O(n log n), inte O(n^2). Koden visar mergesortering.
# Merge sort: O(n log n)
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(a, b):
res, i, j = [], 0, 0
while i < len(a) and j < len(b):
if a[i] <= b[j]: res.append(a[i]); i+=1
else: res.append(b[j]); j+=1
return res + a[i:] + b[j:]
print(merge_sort([5,2,8,1,9,3])) # [1,2,3,5,8,9]Amortiserad komplexitet
Amortiserad analys beräknar den genomsnittliga kostnaden över många operationer. Pythons append har amortiserad komplexitet O(1): det går vanligtvis direkt, medan den sällsynta storleksändringen på O(n) fördelas tunt över alla anrop till append.
# Dynamic array append is O(1) amortised
import sys
lst = []
capacities = []
for i in range(16):
lst.append(i)
capacities.append(sys.getsizeof(lst))
# Size jumps show reallocation events
for i, c in enumerate(capacities):
if i > 0 and capacities[i] != capacities[i-1]:
print(f'Realloc at i={i}, new size={c} bytes')Känna igen komplexitet i kod
En snabb tumregel: räkna loopar. En loop är O(n), två nästlade loopar är O(n^2), och en loop som halverar är O(log n). Oberoende genomgångar adderas; endast nästlade loopar multipliceras. Se koden.
# Two independent passes: O(n) + O(n) = O(n)
def two_passes(nums):
total = sum(nums) # O(n)
mean = total / len(nums)
diffs = [abs(n - mean) for n in nums] # O(n)
return max(diffs) # O(n)
# Overall: O(n) -- NOT O(n^2)
# Nested loops: O(n) * O(n) = O(n^2)
def all_pairs(nums):
pairs = []
for i in range(len(nums)): # O(n)
for j in range(i+1, len(nums)): # O(n)
pairs.append((nums[i], nums[j]))
return pairs # O(n^2)Grunderna i minneskomplexitet
Minneskomplexitet mäter det extra minne du använder utöver indata. En vändning på plats är O(1); en hash map är O(n). När du byter tid mot minne ska du alltid ange båda.
# O(1) space: reverse in-place
def reverse_inplace(arr):
l, r = 0, len(arr) - 1
while l < r:
arr[l], arr[r] = arr[r], arr[l]
l += 1; r -= 1
# O(n) space: create reversed copy
def reverse_copy(arr):
return arr[::-1]
a = [1, 2, 3, 4, 5]
reverse_inplace(a)
print(a) # [5, 4, 3, 2, 1]Prata om komplexitet på intervjuer
Ange alltid komplexiteten utan att bli ombedd: "Det här tar O(n log n) tid och använder O(n) minne." Erbjud sedan ett snabbare alternativ. Den vanan signalerar verklig senioritet.
# Example of explaining complexity step by step
def two_sum(nums, target):
# O(n) time: one pass through nums
# O(n) space: hash map stores up to n elements
seen = {} # value -> index
for i, n in enumerate(nums):
complement = target - n
if complement in seen: # O(1) lookup
return [seen[complement], i]
seen[n] = i
return []
print(two_sum([2, 7, 11, 15], 9)) # [0, 1]Snabbtest
Snabbtest — visa vad du har lärt dig om Big-O och komplexitetsklasser. En fråga, det här klarar du. 🎯
Lektionssammanfattning
Sammanfattning: Big-O beskriver tillväxten i värsta fallet med utelämnade konstanter, du känner till klasserna från O(1) till O(n!), och oberoende loopar adderas medan nästlade loopar multipliceras.
Lär dig Förberedelse inför kodningsintervjuer med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 90
- Lektioner
- 360
Vanliga frågor
Är lektionen ”Big-O-notation från grunden” gratis?
Ja – hela texten till ”Big-O-notation från grunden” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Förberedelse inför kodningsintervjuer, kan Ni uppgradera till CoddyKit PRO. Kursen i Förberedelse inför kodningsintervjuer innehåller totalt 4 lektioner.
Vad lär jag mig i ”Big-O-notation från grunden”?
Förstå varför asymptotisk tillväxt är viktig, hur konstanter och termer av lägre ordning utelämnas och hur ni snabbt tolkar Big-O. Ni övar på Förberedelse inför kodningsintervjuer med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Förberedelse inför kodningsintervjuer?
Du behöver inga förkunskaper. Utbildningen i Förberedelse inför kodningsintervjuer på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Big-O-notation från grunden”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Förberedelse inför kodningsintervjuer-lektionen?
Ja. Varje Förberedelse inför kodningsintervjuer-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Big-O-notation från grunden
- Analysera loopar och nästlade loopar
- Rekursion och metoden med rekursionsträd
- Rymdkomplexitet och avvägningar