Contents

Computer Science › Algorithms

Time Complexity

How the number of steps grows with input size.

Also known as: runtime complexity, algorithm complexity, running time

Time complexity describes how the number of steps an algorithm takes grows as the input gets bigger. It’s expressed in Big O notation, and it answers: if I double the data, what happens to the running time?

Count how the work scales with n, the input size:

def first(items):              # O(1): one step, however long the list is
    return items[0]

def total(items):              # O(n): one step per item
    return sum(items)

def has_duplicates(items):     # O(n²): compare every pair
    for i in range(len(items)):
        for j in range(i + 1, len(items)):
            if items[i] == items[j]:
                return True
    return False

def has_duplicates_fast(items):    # O(n): a set remembers what's been seen
    return len(set(items)) != len(items)

How to work it out

  • A single loop over n items: O(n).
  • A loop inside a loop over the same data: O(n²).
  • Halving the problem each step: O(log n).
  • Steps one after another add (O(n) + O(n²) is O(n²)). Nesting multiplies.
  • Drop constants and lower-order terms (complexity classes).
  • Watch for hidden loops: x in some_list, list.insert(0, x), string concatenation in a loop, a database query per item (N+1 queries).

Which case?

Complexity is usually stated for the worst case, sometimes the average (best, worst and average case).

What it’s for

  • Predicting how code scales before it meets real data.
  • Choosing between approaches: a dictionary lookup or a list scan?
  • Spotting performance bugs. “It was fast in testing and slow in production” often means a quadratic algorithm met large input.

Time complexity ignores constants and real hardware, so measure when it matters (premature optimization). Memory has its own version (space complexity).