Big O Notation Explained: Time and Space Complexity
Blog / Big O Notation Explained: Time and Space Complexity
What actually is big O notation? And why do interviewers always ask for it?
Why Not Measure in Seconds
You might be tempted to just time your code in seconds. But timing code depends on the machine, the programming language, and what else is running.This makes it impossible to compare algorithms fairly.This is where Big O notation comes in. Big O describes how the number of steps grows as the input size, n, grows. It provides an upper bound on that growth, written as a mathematical function of n.O(1): No Loop
O(1) is also known as constant time. Here, the number of steps does not change as n gets larger. A classic example is reading an element from an array by its index.def get_first(arr):
return arr[0]
O(n): One Loop
O(n) means linear time. This happens when you have one loop over the input. The number of steps grows in a straight line with n.Finding the maximum value in an array is a perfect example.maximum = arr[0]
for num in arr:
if num > maximum:
maximum = num
O(n²): Nested Loops
Sometimes you need to compare every item against every other item. This introduces nested loops.A loop inside a loop over the same input does n times n steps. We call this O(n²) or quadratic time. Doubling your input size makes the algorithm four times slower.A common example is comparing every pair to find a duplicate.for i in range(n):
for j in range(n):
if i != j and arr[i] == arr[j]:
return True
O(log n): Halving
O(log n) is logarithmic time. It describes an algorithm where each step halves what is left to check.A great example is binary search on a sorted array. If you have a million items, finding your target takes only about 20 steps.while left <= right:
mid = (left + right) // 2
if arr[mid] == target: return mid
elif arr[mid] < target: left = mid + 1
else: right = mid - 1

O(n log n): Halving at Every Level
O(n log n) means doing O(log n) levels of O(n) work. You will see this as the cost of efficient sorts like merge sort.Merge sort keeps splitting the array in half until every piece is a single item. Just like binary search, that takes about log n levels.
O(2ⁿ): Every Call Branches in Two
On the extreme end, we have exponential time or O(2ⁿ). This usually happens with a recursive function that calls itself twice per call.The naive Fibonacci algorithm is a famous example. Every time n grows by just one, the amount of work doubles.def fibonacci(n):
if n <= 1: return n
return fibonacci(n - 1) + fibonacci(n - 2)

Dropping Constants and Lower-Order Terms
When calculating Big O, we only keep the fastest growing term. We also drop all constant multipliers.This is because for very large values of n, the smaller details stop mattering.Take two separate loops, one after the other:for num in arr:
print(num)
for num in arr:
print(num * 2)
for i in range(n):
for j in range(n):
print(i, j)
for i in range(n):
print(i)
Time vs Space Complexity
So far we have focused on time, but algorithms also consume memory. This brings us to space complexity.The exact same notation describes how extra memory usage grows with n. Building a new array of size n takes O(n) space. Swapping elements in place takes O(1) space.You often trade space for time. Instead of using nested loops to find a duplicate in O(n²) time and O(1) space, you can use a hash set.The hash set finds a duplicate in O(n) time, but it costs O(n) space to store the seen items.Best, Average and Worst Case
An algorithm might run faster or slower depending on the exact input.If you do a linear search, you might find your item on the very first try. This is the best case. Or the item might be at the very end, which is the worst case.In interviews, Big O usually refers to the worst case scenario. However, there are exceptions where the average case matters more.For example, quicksort runs in O(n log n) time on average, but drops to O(n²) time in the worst case.Recap
Here are the main growth curves from fastest to slowest.| Complexity | How to spot it in code | Example |
|---|---|---|
| O(1) | No loop | Reading an array element |
| O(log n) | Halving the input | Binary search |
| O(n) | One loop | Finding the maximum |
| O(n log n) | O(log n) levels of O(n) work | Merge sort |
| O(n²) | Nested loops | Comparing every pair |
| O(2ⁿ) | Two recursive calls per step | Naive Fibonacci |
About TechPrep
Never walk into a technical interview unprepared again. TechPrep empowers software engineers to stop guessing and start getting offers. We provide the exact questions asked by tech companies across Data Structures & Algorithms, System Design, Low-Level Design & AI coding rounds. Don't leave your career up to chance. Join thousands of engineers who have successfully navigated the tech hiring maze and landed roles at top tech companies.