metricas-algoritmos-mas-alla-big-o

Algorithm Metrics

  • 5 min

The metrics of an algorithm are criteria for comparing solutions beyond how long they take.

In the previous article we focused on the Big O notation, which is used to measure how execution time grows as input size increases. It’s a very useful tool, but it doesn’t tell the whole story.

An algorithm can be fast and still be a bad choice. It might consume too much memory, lose precision, be difficult to maintain, or break with slightly unusual data. So today we’re going to look at the complete dashboard.

Summary

When we choose an algorithm, we don’t just look at the speedometer. We also need to look at consumption, stability, and maintainability.

MetricKey questionWhen it matters most
TimeHow does speed scale?Large data volumes
SpaceHow much extra memory does it use?Systems with little RAM or lots of data
StabilityDoes it preserve previous order?Multi-criteria sorting
PrecisionIs the result exact or approximate?Scientific computing, finance, simulation
RobustnessWhat happens with unusual inputs?Production software
ReadabilityCan it be maintained without suffering?Almost always

Space complexity

If time complexity measures “how long it takes,” then space complexity measures how much memory it needs.

There’s often a classic trade-off: we can make something faster if we use more memory, or we can save memory if we accept recalculating things.

For example, a cache stores previous results to avoid recalculating them. This can speed up a program tremendously, but at the cost of RAM usage.

It’s worth distinguishing two things:

  • Input space: memory occupied by the data we already receive.
  • Auxiliary space: extra memory the algorithm needs to work.

Typically, when we analyze memory, we are especially interested in auxiliary space.

Suppose we want to reverse an array:

[1, 2, 3, 4] -> [4, 3, 2, 1]
Copied!

One option is to create a new array and copy the elements in reverse order. It’s simple, but uses additional O(n) memory.

Another option is to swap the first element with the last, the second with the second-to-last, and so on. This modifies the original array and uses O(1) memory. This is called working in-place.

In embedded systems, mobile applications, or processes with massive amounts of data, running out of memory is usually worse than taking a little longer.

Stability

Stability is especially important in sorting algorithms.

A sorting algorithm is stable if, when two elements have the same key, it maintains their relative order from before.

It seems like a minor detail, until you do chained sorts. For example, a list of employees already sorted by name:

NameDepartment
AnaSales
CarlosMarketing
DanielSales

If we now sort by department with a stable algorithm, Ana will still come before Daniel within Sales. If the algorithm is not stable, that order can be lost.

Algorithms like Merge Sort are stable. QuickSort, in its classic implementations, is typically not. In practice, modern libraries can use hybrid, optimized variants.

Accuracy and numerical precision

Another criterion is whether the algorithm returns the exact solution or an approximation.

There are problems where finding the perfect solution is too expensive. In these cases, heuristics or approximations are used to give a sufficiently good answer in a reasonable time.

This is common in routing, optimization, artificial intelligence, or scheduling problems. We don’t always want “the perfect answer.” Often we want a good answer before the coffee gets cold.

Numerical stability

In numerical computing, how rounding errors behave also matters.

Computers represent many real numbers with floating point (float, double). This introduces small errors:

console.log(0.1 + 0.2); // 0.30000000000000004
Copied!

An algorithm is numerically unstable if those small errors amplify step by step until they ruin the final result.

Robustness

Robustness measures how an algorithm behaves with incorrect, unexpected, or malicious inputs.

A fragile algorithm assumes everything will be perfect:

  • the list is never empty,
  • the user always types a number,
  • the file always exists,
  • a null never arrives,
  • it never divides by zero.

Reality, of course, has other hobbies.

A robust algorithm validates inputs, considers edge cases, and fails gracefully when it cannot continue.

Readability and maintainability

This metric seems less technical, but it carries enormous weight in real projects.

Sometimes we can make an algorithm 5% faster using hard-to-read tricks. The question is whether it’s worth it. If that code is going to be maintained for years, perhaps the human cost is greater than the CPU savings.

Anyone can write code that a computer understands. The challenge is to write code that people also understand.

It doesn’t mean performance doesn’t matter. It means that clarity is also part of the design.