Time complexity measures how the running time of an algorithm grows as the input size n increases. It focuses on the rate of growth, not exact times.
We measure the worst case (maximum steps for any input of size n) unless specified otherwise.
Big-O notation is a mathematical notation that describes the upper bound of an algorithm's time complexity — how many operations it performs as a function of input size n in the worst case.
3n² + 5n + 2 → O(n²)| Big-O | Name | Description | Example |
|---|---|---|---|
| O(1) | Constant | Same time regardless of n | Array index access, hash table lookup |
| O(log n) | Logarithmic | Halves problem each step | Binary search |
| O(n) | Linear | Proportional to n | Linear search, single loop |
| O(n log n) | Linearithmic | n × log n steps | Merge sort, quicksort (average) |
| O(n²) | Quadratic | Nested loops over n | Bubble sort, insertion sort (worst) |
| O(2ⁿ) | Exponential | Doubles with each new element | Brute-force subset enumeration |
| O(n!) | Factorial | Grows factorially | Brute-force TSP, all permutations |
n=10: O(1)=1, O(log n)≈3, O(n)=10, O(n log n)≈33, O(n²)=100, O(2ⁿ)=1024 n=100: O(1)=1, O(log n)≈7, O(n)=100, O(n log n)≈664, O(n²)=10000, O(2ⁿ)=huge!
Order from most to least efficient: O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(2ⁿ) < O(n!)
// O(1) — constant time
x = arr[5]
// O(n) — single loop
for i in range(n):
print(arr[i])
// O(n²) — nested loops
for i in range(n):
for j in range(n):
print(arr[i], arr[j])
// O(log n) — halving each iteration
left, right = 0, n-1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target: return mid
elif arr[mid] < target: left = mid + 1
else: right = mid - 1
Space complexity measures memory usage as n grows, using the same Big-O notation.
| Complexity | Example |
|---|---|
| O(1) space | Sorting in-place (e.g. bubble sort) |
| O(n) space | Storing a copy of the array |
| O(n²) space | Storing an n×n matrix |
8 questions · instantly marked · AQA 7517 standard
| Term | Definition |
|---|
10 questions · 10 minutes