Big-O: upper bound
f(n) = O(g(n)) means f grows no faster than g, up to a constant factor and for large enough n. The standard claim in informal speech: "merge sort is O(n log n)" gives the worst-case ceiling.
Core CS Concept
Asymptotic complexity analysis explained from the ground up. 8 common complexity classes from O(1) through O(2^n), Big-O vs Big-Theta vs Big-Omega distinctions, amortized analysis, and a cross-language benchmark table showing actual measured runtimes from n=10 through n=10,000 in Java, Python, C++, and JavaScript. Verified CS graduates from CMU, MIT, and Stanford, starting at $20 per task.
What it means
Big-O notation describes how an algorithm scales with input size, hiding constants and lower-order terms so the dominant growth rate stays visible at scale.
Same algorithm, different constants: Python is roughly 20x slower than C++, but the asymptotic class (O(n), O(n log n), O(n^2)) stays identical across Java, Python, C++, and JavaScript.
Primary example
// O(1) constant - one operation regardless of input size
public int firstElement(int[] arr) {
return arr[0];
}
// O(n) linear - one pass through the input
public int sum(int[] arr) {
int total = 0;
for (int x : arr) total += x;
return total;
}
// O(n^2) quadratic - nested loop over input
public boolean hasDuplicate(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) return true;
}
}
return false;
}
Three asymptotic bounds
f(n) = O(g(n)) means f grows no faster than g, up to a constant factor and for large enough n. The standard claim in informal speech: "merge sort is O(n log n)" gives the worst-case ceiling.
f(n) = Theta(g(n)) bounds f both above and below by constant multiples of g. The complete claim for merge sort is Theta(n log n); CS161 graders deduct points for using O when Theta is provable.
f(n) = Omega(g(n)) means f grows no slower than g. Used to prove no algorithm can do better than a certain rate, like the comparison-sort Omega(n log n) decision-tree lower bound.
Cross-language
# O(1) constant - dict lookup
def get(d, key):
return d.get(key)
# O(log n) logarithmic - binary search
def binary_search(arr, target):
lo, hi = 0, len(arr) - 1
while lo <= hi:
mid = (lo + hi) // 2
if arr[mid] == target: return mid
if arr[mid] < target: lo = mid + 1
else: hi = mid - 1
return -1
# O(n log n) linearithmic - merge sort
def merge_sort(arr):
if len(arr) <= 1: return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
# O(2^n) exponential - naive recursive Fibonacci
def fib(n):
if n < 2: return n
return fib(n - 1) + fib(n - 2) // std::vector dynamic-array growth
// Most push_back calls are O(1); resize-and-copy is O(n).
// Amortized cost per push_back is O(1).
#include <vector>
std::vector<int> v;
for (int i = 0; i < 1000000; i++) {
v.push_back(i); // O(1) amortized
}
// Internal growth pattern (GCC libstdc++ default):
// capacity doubles when full: 1, 2, 4, 8, 16, ..., 524288, 1048576
// 20 resize events total for 1 million pushes
// Total work: 1+2+4+...+1048576 = 2097151 element copies
// Per push: 2097151 / 1000000 ~= 2.1 amortized copies FAQ
Submit your assignment and get expert, pedagogical help within 12 hours. Every solution ships with line-by-line comments, complexity analysis, and unlimited revisions.
Get Big-O Notation Help