Asymptotic notation is a mathematical tool used to describe the behavior of an algorithm in terms of time or space complexity as the input size approaches infinity. These notations provide an abstract way to express the efficiency and growth rate of algorithms, allowing us to compare different algorithms and understand their scalability for large inputs.
The three main asymptotic notations used in computer science are:
Each notation describes the algorithm’s performance from a different perspective, such as the worst-case, best-case, or average-case behavior.
Big-O notation describes the upper bound of an algorithm’s running time or space complexity. It represents the worst-case scenario, showing the maximum growth rate of the algorithm as the input size increases. Big-O notation is typically used to express an algorithm’s upper limit on performance.
An algorithm is said to have a time or space complexity of O(f(n)) if, for sufficiently large n, the algorithm’s running time or space will not exceed a constant multiple of f(n). Formally, there exist constants c and n₀ such that for all n ≥ n₀, the running time T(n) satisfies:
for (int i = 0; i < n; i++) {
if (arr[i] == target) {
return i;
}
}
Big-Ω notation describes the lower bound of an algorithm’s running time or space complexity. It represents the best-case scenario, showing the minimum growth rate of the algorithm as the input size increases. It gives an idea of the minimum time or space an algorithm will need to solve a problem.
An algorithm is said to have a time or space complexity of Ω(f(n)) if, for sufficiently large n, the algorithm's running time or space will be at least a constant multiple of f(n). Formally, there exist constants c and n₀ such that for all n ≥ n₀, the running time T(n) satisfies:
Big-Θ notation provides a tight bound on an algorithm’s running time or space complexity. It represents both the upper and lower bounds, giving an exact description of the algorithm’s growth rate. When an algorithm’s time complexity is described as Θ(f(n)), it means the algorithm’s growth rate is bounded both from above and below by f(n), within constant factors.
An algorithm is said to have a time or space complexity of Θ(f(n)) if there exist constants c₁, c₂, and n₀ such that for all n ≥ n₀, the running time T(n) satisfies:
Little-o notation describes the strict upper bound of an algorithm's growth rate. It is similar to Big-O, but it implies that the algorithm’s running time or space complexity grows strictly slower than a function f(n) as n grows large.
An algorithm is said to have a time or space complexity of o(f(n)) if, for any constant c > 0, there exists an n₀ such that for all n ≥ n₀, the running time T(n) satisfies:
Little-Ω notation describes the strict lower bound of an algorithm’s running time or space complexity. It means that the algorithm’s growth rate will eventually outpace a given function f(n).
An algorithm is said to have a time or space complexity of ω(f(n)) if, for any constant c > 0, there exists an n₀ such that for all n ≥ n₀, the running time T(n) satisfies:
| Notation | Description | Bound | Example |
|---|---|---|---|
| Big-O | Upper bound (worst-case) | T(n) ≤ c * f(n) | O(n²) for bubble sort |
| Big-Ω | Lower bound (best-case) | T(n) ≥ c * f(n) | Ω(n) for linear search |
| Big-Θ | Tight bound (exact growth rate) | c₁ * f(n) ≤ T(n) ≤ c₂ * f(n) | Θ(n) for linear search |
| Little-o | Strict upper bound (grows strictly slower) | T(n) < c * f(n) | o(n²) for an algorithm slower than quadratic growth |
| Little-Ω | Strict lower bound (grows strictly faster) | T(n) > c * f(n) | ω(n log n) for algorithms that grow faster than linearithmic |
Asymptotic notations are essential tools in algorithm analysis, allowing us to express and compare the growth rates of different algorithms in a rigorous and abstract way. By using Big-O, Big-Ω, and Big-Θ, we can describe an algorithm's performance in terms of time and space complexity, and choose the most efficient one for a given problem.
Open this section to load past papers