## The Mastery of Computer Programming: Primary Algorithms - Sykalo Eugene 2023

# Asymptotic notation

Analysis of Algorithms

## Introduction to Asymptotic Notation

In computer science, asymptotic notation is used to describe how an algorithm's performance changes as the input size increases. This notation allows us to compare the efficiency of different algorithms and to understand the growth rate of an algorithm's running time.

Asymptotic notation is typically expressed using mathematical formulas. The most commonly used asymptotic notations are Big O, Omega, Theta, and Little O.

Big O notation describes the upper bound of an algorithm's performance. It provides an upper limit on the growth rate of the algorithm's running time as the input size increases. This means that the algorithm's running time will never exceed the function used in the notation.

Omega notation describes the lower bound of an algorithm's performance. It provides a lower limit on the growth rate of the algorithm's running time as the input size increases. This means that the algorithm's running time will never be less than the function used in the notation.

Theta notation describes the tight bound of an algorithm's performance. It provides both upper and lower limits on the growth rate of the algorithm's running time as the input size increases. This means that the algorithm's running time will always be between the functions used in the notation.

Little O notation is similar to Big O notation, but with a stricter requirement. It provides an upper limit on the growth rate of the algorithm's running time as the input size increases, but the growth rate must be strictly less than the function used in the notation.

Asymptotic notation is an important concept in computer science, as it allows us to compare the efficiency of different algorithms and to understand how an algorithm's performance changes as the input size increases.

## Big O Notation

Big O notation is used to describe the upper bound of an algorithm's performance. It provides an upper limit on the growth rate of the algorithm's running time as the input size increases.

In other words, Big O notation tells us how quickly the runtime of an algorithm increases as the size of its input grows. For example, if an algorithm has a Big O notation of O(n), it means that its runtime increases linearly with the size of its input.

The Big O notation is usually expressed as a mathematical function, where n represents the size of the input. For example, the function f(n) = n^2 + 3n + 1 has a Big O notation of O(n^2), because the term with the highest power of n is n^2.

When analyzing the performance of an algorithm, it is often useful to know its Big O notation. This allows us to compare the efficiency of different algorithms and to understand how an algorithm's performance changes as the input size increases.

It is important to note that the Big O notation represents an upper bound on an algorithm's performance. This means that the actual runtime of the algorithm may be lower than the function used in the notation. However, the Big O notation gives us an idea of the worst-case scenario for an algorithm's performance.

## Omega Notation

Omega notation is used to describe the lower bound of an algorithm's performance. It provides a lower limit on the growth rate of the algorithm's running time as the input size increases. In other words, it gives us a guarantee that the algorithm will take at least a certain amount of time to complete, regardless of the input size.

For example, consider an algorithm that sorts an array of n values. The best-case scenario for this algorithm is when the array is already sorted, in which case the algorithm will take O(n) time to complete. However, in the worst-case scenario, the array is reverse sorted, and the algorithm will take O(n^2) time to complete. In this case, we can use Omega notation to describe the lower bound of the algorithm's performance.

The Omega notation is usually expressed as a mathematical function, where n represents the size of the input. For example, the function f(n) = n^2 + 3n + 1 has an Omega notation of Omega(n^2), because the term with the highest power of n is n^2.

When analyzing the performance of an algorithm, it is often useful to know its Omega notation. This allows us to understand the lower limit of the algorithm's performance, and to compare it with other algorithms that have a similar upper bound (as described by their Big O notation).

It is important to note that the Omega notation represents a lower bound on an algorithm's performance. This means that the actual runtime of the algorithm may be higher than the function used in the notation. However, the Omega notation gives us an idea of the best-case scenario for an algorithm's performance.

## Theta Notation

Theta notation is used to describe the tight bound of an algorithm's performance. It provides both upper and lower limits on the growth rate of the algorithm's running time as the input size increases. This means that the algorithm's running time will always be between the functions used in the notation.

For example, consider an algorithm that sorts an array of n values. The best-case scenario for this algorithm is when the array is already sorted, in which case the algorithm will take O(n) time to complete. In the worst-case scenario, the array is reverse sorted, and the algorithm will take O(n^2) time to complete. However, in the average case, the algorithm may take O(n log n) time to complete. In this case, we can use Theta notation to describe the tight bound of the algorithm's performance.

The Theta notation is usually expressed as a mathematical function, where n represents the size of the input. For example, the function f(n) = n^2 + 3n + 1 has a Theta notation of Theta(n^2), because the term with the highest power of n is n^2.

When analyzing the performance of an algorithm, it is often useful to know its Theta notation. This allows us to understand the tight bound of the algorithm's performance, and to compare it with other algorithms that have similar upper and lower bounds (as described by their Big O and Omega notations).

It is important to note that the Theta notation represents a tight bound on an algorithm's performance. This means that the actual runtime of the algorithm will always be between the functions used in the notation, up to a constant factor. In other words, the algorithm's performance will never exceed the upper bound or fall below the lower bound by more than a constant factor.

## Little O Notation

Little O notation is used to describe the upper bound of an algorithm's performance, but with a stricter requirement than Big O notation. It provides an upper limit on the growth rate of the algorithm's running time as the input size increases, but the growth rate must be strictly less than the function used in the notation.

For example, consider an algorithm that has a running time of f(n) = n^2 + 3n + 1. If we say that the algorithm has a Little O notation of o(n^3), it means that the growth rate of the algorithm's running time is strictly less than n^3. In other words, the algorithm's running time grows slower than n^3 as the input size increases.

Little O notation is useful when we want to describe an algorithm whose running time grows much slower than the upper bound described by its Big O notation. For example, if an algorithm has a Big O notation of O(n^2), but we know that its running time actually grows at a rate of n log n, we can use Little O notation to describe this tighter bound.

It is important to note that Little O notation represents an upper bound on an algorithm's performance, but with a stricter requirement than Big O notation. This means that the actual runtime of the algorithm may be lower than the function used in the notation, but the growth rate of the algorithm's running time must be strictly less than the function used in the notation.

## Comparison of Asymptotic Notations

When analyzing the performance of an algorithm, it is important to understand the different asymptotic notations and their use cases. The following is a comparison of the different asymptotic notations:

- Big O notation provides an upper bound on an algorithm's performance. It tells us how quickly the runtime of an algorithm increases as the size of its input grows. It is useful for describing the worst-case scenario for an algorithm's performance.
- Omega notation provides a lower bound on an algorithm's performance. It gives us a guarantee that the algorithm will take at least a certain amount of time to complete, regardless of the input size. It is useful for describing the best-case scenario for an algorithm's performance.
- Theta notation provides both upper and lower bounds on an algorithm's performance. It tells us that the algorithm's running time will always be between the functions used in the notation. It is useful for describing the average-case scenario for an algorithm's performance.
- Little O notation provides an upper bound on an algorithm's performance, but with a stricter requirement than Big O notation. It is useful when we want to describe an algorithm whose running time grows much slower than the upper bound described by its Big O notation.

When comparing the different asymptotic notations, it is important to consider the use case of the algorithm being analyzed. For example, if we are analyzing an algorithm for real-time systems, we may be more interested in the worst-case scenario (as described by Big O notation) than in the average-case scenario (as described by Theta notation).

One common mistake when using asymptotic notation is to focus too much on the notation itself, rather than on the underlying algorithm. It is important to remember that asymptotic notation is just a tool for describing an algorithm's performance, and that it should be used in conjunction with other analysis techniques such as profiling and benchmarking.