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.
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.
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.
If key is expensive, total runtime can be significantly larger even though complexity class remains linear.
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:
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:
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()areO(1)because they are built-ins implemented in C. - Ignoring expensive
keyfunctions, 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.

