Big O Notation for Dummies
By: Franchely Portorreal
Tags: Coding, Software Engineering, Programming, Algorithms

The best time complexity in Big O notation is O(1). This includes algorithms that take pretty much the same amount of time to run no matter how long or short a list. The examples below are super simple, but you can see why they don’t take very long:

This also includes mathematical operations within an algorithm that don’t rely on constants: “5 * 250 / 2,” for example. These methods aren’t really sorting or searching to compare data until one matches a condition; they’re simply accessing fixed points in an array or returning a value, and no matter whether the list has 10 or 100 numbers in it, it’ll take about the same time to run. This is called constant time, and it is ideal, although it’s hard to keep a complex algorithm running that fast.

O(n) gets a little more complicated, the variable “n” being the size of the data you are working on. This usually represents an algorithm that has to sort through each item in a list to find the one it’s looking for, or ones where the algorithm uses each item and alters or combines them in some way. Some people call these brute force algorithms because of the way they go through each item no matter what. O(n) is also called linear time.

Because a set of data might grow to an unmanageable size, there’s another time complexity that is better than O(n), referred to as O(log n). The log here stands for logarithm, which you could think of as the opposite of an exponent. So for example, we know that 2⁴ is 16, the number 4 being the exponent. So 2, raised to the 4th power, is equal to 16. Logarithms deal with trying to find what the exponent is if you already have the value. Logarithms answer the question, “how many times do we have to multiply 2 in order to get 16?” O(log n) is also called logarithmic time.

The way O(log n) works is by using binary search in a sorted array. A binary search halves the list and just searches one half. If the data you’re looking for is in that half, it halves it again and repeats the search until there’s nothing left to split. This way of searching becomes much more efficient when you’re working with large sets of data, because it discards one half each time it searches.

The last time complexity I will cover here is O(n²), also called quadratic time. This one is pretty bad, as it starts out okay and then very quickly becomes slow. This time complexity usually deals with nested data, and the reason it has a bad runtime is because not only do you have to sort through every item in a list, but you also have to sort through every item within them.

In the example above, let’s say you had an array with five students in it, and each of those students was actually another array containing five details about the student. This algorithm will have to iterate through a total of 25 times, which is 5². Deeper nesting will result in O(n³), O(n⁴), etc.

(In Big O notation, constants are ignored and replaced with n, because the size could be anything, but the order of magnitude is more easily quantified.)

Below is a handy chart that gives you a visual reference on the different types of runtime complexities.

Big O can get very complex, and it can be hard to conceptualize. The few things I was able to learn so far are really just the tip of the iceberg. However, once you understand why and how it works, it’s easier to understand some of the more complex ideas. Hopefully if you’re starting from zero like I was, this helps explain it in a straightforward way. Will I ever actually learn to calculate Big O? Stay tuned to find out!