Big O Notation (or the Big O) is used to describe how long and complex an operation will be based on its input.

Complexity could mean that an operation takes N amount of time, or N amount of memory, N CPU resources, etc.

There are some notations to describe this:

`O(n)`

-> The complexity grows linearly based on the size of the input.`O(n^2)`

-> Grows at a square ratio of its input.`O(n^3)`

-> Grows at a cube ratio of its input.`O(n^x)`

-> And so on.

Note that the previous notations showcase that complexity always grows, at minimum as `O(n)`

. But what if the complexity grows slower than linearly?

This is where `logarithm`

notations can help describe those complexities.

But first, what is `logarithm`

or `log`

?

A logarithm is the exponent on which a number is raised, for example:

```
b^p = n
2^3 = 2x2x2
2^3 = 8
```

In this case, `p`

is the logarithm

Another example:

```
log(10)^10,000 = x
10^x = 10,000
10^4 = 10,000
log(10)^10,000 = 4
```

Now that we know that the `log`

is just an exponent to raise a base (`p`

) we can say that:

`O(log(n))`

-> grows at a logarithmic rate based on its input.

complexity described in

`O(log(n))`

is used to define “efficient” algorithms.

**But what all this means?**

Take `binary_search`

for example:

Binary Search is a searching algorithm used in a sorted array by repeatedly dividing the search interval in half. The idea of binary search is to use the information that the array is sorted and reduce the time complexity to O(Log n).

```
def binary_search(sorted_list, value):
low = 0
high = len(sorted_list) - 1
while low <= high:
mid = (low + high) // 2
if sorted_list[mid] == value:
return mid
elif value < sorted_list[mid]:
high = mid - 1
else:
low = mid + 1
return -1
```

On each iteration of this loop the input size is halved, which means that the exponent or `p`

of this function is `O(log2(n))`

To solve a `O(log(n))`

, take for example a list of 1024 elements and find its log.

```
O(log(2)^n)) = len(sorted_list)
O(log(2)^n)) = 1024
2^x = 1024
2^10 = 1024
log(2)^10) = 1024
```

It takes only `10`

iteratios to find the value in a list of 1024 elements.

Also,

`O(log(log(n)))`

-> Grows at a double logarithm rate. or the complexity increases slower`O(log(log(log(n))))`

-> and so on, similar to`O(n^x)`

.