Python
Big O Notation
min function
max function
Algorithm Efficiency

Big O of min and max in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The time complexity of Python's built-in min() and max() is generally O(n) for iterables, because each element must be examined at least once to guarantee the correct result. This remains true regardless of whether values are numbers, strings, or custom objects with comparison methods. There are a few special cases where O(1) access exists, such as retrieving the first or last element of a pre-sorted list, but that is not what min()/max() do internally. Understanding this helps you make better choices in tight loops and large-data pipelines.

Why min and max Are Linear

For an unsorted iterable of size n, Python keeps a current best candidate and compares each new element against it.

python
1def simple_max(xs):
2    best = xs[0]
3    for x in xs[1:]:
4        if x > best:
5            best = x
6    return best

This performs n-1 comparisons, which is O(n) time. Memory usage is O(1) beyond the iterable itself.

The same logic applies to min().

Complexity by Input Type

The container type (list, tuple, generator, set) does not change asymptotic complexity for a full scan.

python
max([3, 1, 9, 2])          # O(n)
max((3, 1, 9, 2))          # O(n)
max(x for x in range(10))  # O(n)

However, constants differ:

  • Lists and tuples have low iteration overhead.
  • Generators may include expensive production logic.
  • Custom objects may have expensive comparison methods.

So wall-clock time can vary while Big O stays O(n).

key= Does Not Change Big O

Using a key function still requires scanning all elements.

python
users = [{"name": "A", "score": 5}, {"name": "B", "score": 8}]
best = max(users, key=lambda u: u["score"])  # O(n)

If key is expensive, total runtime can be significantly larger even though complexity class remains linear.

python
# key function called once per element
slowest = max(paths, key=compute_file_score)

Cache expensive derived values when possible if you call min/max repeatedly.

Repeated Queries: Precompute Instead

If you need many min/max queries over changing data, repeated linear scans may be too slow.

Options include:

  • Keep data sorted and access ends (O(1) query, higher update cost).
  • Use heaps (heapq) for efficient repeated min operations.
  • Maintain running extrema incrementally during streaming ingestion.

Example streaming maximum:

python
1current_max = None
2for x in stream:
3    if current_max is None or x > current_max:
4        current_max = x

This avoids rescanning historical data each time.

Practical Verification Workflow

A reliable way to avoid regressions is to validate the solution in three passes: baseline, controlled change, and repeatability check. First, capture a baseline outcome before you apply fixes. This could be a failing command, a wrong output sample, a stack trace, or a screenshot of current behavior. Second, apply one focused change and rerun exactly the same checks so you can attribute improvements to a specific edit. Third, rerun the checks multiple times or with slightly different inputs to ensure the fix is not accidental or data-specific.

A lightweight template you can adapt for most projects looks like this:

bash
1# 1) reproduce current behavior
2./run_example.sh > before.txt
3
4# 2) apply your change
5# edit config/code based on this article
6
7# 3) verify behavior after change
8./run_example.sh > after.txt
9diff -u before.txt after.txt

If your environment involves tests, add at least one focused regression test that would fail before the fix and pass after it. This turns a one-time troubleshooting success into a durable maintenance improvement, which is especially important when teams rotate ownership or upgrade dependencies later.

Common Pitfalls

  • Assuming min()/max() are O(1) because they are built-ins implemented in C.
  • Ignoring expensive key functions, which can dominate runtime in practice.
  • Recomputing min/max in inner loops when a running value could be maintained.
  • Confusing sorted-container endpoint access with general min()/max() behavior.
  • Benchmarking tiny arrays and extrapolating misleading performance expectations.

Summary

For normal iterable inputs, Python min() and max() are O(n) time and O(1) extra space because they must inspect every element. Built-in implementation details improve constants but not asymptotic complexity. If your workload requires frequent extrema queries, restructure data or maintain running values instead of repeatedly scanning full collections.


Course illustration
Course illustration

All Rights Reserved.