DSA course menu
Big O Notation Explained Simply (With Python Examples)
Learn Big O notation for beginners: what O(1), O(log n), O(n), O(n log n) and O(n²) mean, how to compare them, and the rules for simplifying Big O expressions.
On this page
Big O notation describes how the work an algorithm does grows as its input grows. It does not measure seconds, which depend on the computer. It answers a simpler, more useful question: if the input gets 10 times bigger, roughly how much more work is there?
We write the input size as n: the number of items in a list, characters in a string, nodes in a graph.
The common growth rates#
Here is how many steps each one means for a few input sizes:
import math
print(f"{'n':>6} {'log n':>6} {'n log n':>8} {'n^2':>10} {'2^n':>22}")
for n in [10, 20, 30, 1000]:
two_n = 2 ** n if n <= 64 else "too big to write"
print(f"{n:>6} {round(math.log2(n)):>6} {round(n * math.log2(n)):>8} {n * n:>10} {two_n:>22}") n log n n log n n^2 2^n
10 3 33 100 1024
20 4 86 400 1048576
30 5 147 900 1073741824
1000 10 9966 1000000 too big to writeAt n = 1000, a logarithmic algorithm needs about 10 steps and a quadratic one a million. An exponential one needs a number with 302 digits, far more than any computer could ever finish.
Seeing the difference#
Each function below counts its own steps instead of timing them, so the result is the same on every machine:
def constant(items):
return 1 # one step, whatever the size
def linear(items):
steps = 0
for _ in items:
steps += 1
return steps
def quadratic(items):
steps = 0
for _ in items:
for _ in items:
steps += 1
return steps
def logarithmic(items):
steps, size = 0, len(items)
while size > 1: # halve the problem each time
size //= 2
steps += 1
return steps
for n in [8, 64, 512]:
data = list(range(n))
print(n, constant(data), logarithmic(data), linear(data), quadratic(data))8 1 3 8 64
64 1 6 64 4096
512 1 9 512 262144Multiplying n by 8 adds 3 steps to the logarithmic function, multiplies the linear one by 8, and multiplies the quadratic one by 64.
Simplifying Big O#
Big O keeps only what matters for large n. Two rules do most of the work.
1. Drop constants. A loop that does 3 steps per item is O(3n), which we write as O(n). Doubling n still doubles the work; the 3 does not change the shape.
2. Keep only the biggest term. O(n² + n + 100) becomes O(n²). When n is a million, n² is a trillion and the + n is a rounding error:
n = 1_000_000
print(n * n)
print(n * n + n + 100)
print(f"{(n + 100) / (n * n + n + 100):.10%} of the total comes from n + 100")1000000000000
1000001000100
0.0001000099% of the total comes from n + 100Different inputs keep different letters: looping over a list of size n and then a list of size m is O(n + m), not O(n).
Best, average and worst case#
The same algorithm can take different amounts of work on different inputs. Searching a list for a value:
- best case: it is the first item, O(1);
- worst case: it is the last item or missing, O(n);
- average case: about halfway, n/2 steps, which is still O(n).
Unless someone says otherwise, Big O normally means the worst case: a guarantee that the algorithm never does worse.
Common mistakes#
Practice#
Practice exercise
Give the Big O of each function in terms of the length n of items:
def a(items):
return items[0] + items[-1]
def b(items):
total = 0
for x in items:
total += x
for x in items:
total -= 1
return total
def c(items):
pairs = 0
for i in range(len(items)):
for j in range(i + 1, len(items)):
pairs += 1
return pairsShow hint
For c, count the pairs: the inner loop runs n−1 times, then n−2, then n−3… The sum of 1 + 2 + … + (n−1) is n(n−1)/2.
Show solution
ais O(1): two index reads, whatever the length.bis O(n): two separate loops is O(2n), and constants are dropped.cis O(n²): it does n(n−1)/2 steps. Dropping the constant ½ and the smaller term leaves n².
You can check c by counting:
def c(items):
pairs = 0
for i in range(len(items)):
for j in range(i + 1, len(items)):
pairs += 1
return pairs
for n in [10, 100, 1000]:
print(n, c(range(n)), n * (n - 1) // 2)10 45 45
100 4950 4950
1000 499500 499500Key takeaway#
Next, apply these rules to real code in Analysing Time Complexity.
Finished this lesson?
Related lessons
Recommended DSA resources
- Cracking the Coding Interview by Gayle Laakmann McDowell
189 practice questions with solutions, for coding interview preparation.
Some links are affiliate links. If you buy through them, Laviyx Learn may earn a commission at no extra cost to you. As an Amazon Associate, we earn from qualifying purchases.