โฑ๏ธ Time & Space Complexity Analysis
๐ข Beginner Foundation 45 min read
๐ค What is Complexity Analysis?
Complexity Analysis measures how the time and space requirements of an algorithm grow as the input size grows. It helps us compare algorithms without running them on actual hardware.
Imagine two sorting algorithms. One takes 1 second for 1000 items, the other takes 10 seconds. But what happens with 1 million items? Complexity analysis answers this before you write production code.
๐ Big O Notation - The Universal Language
Big O describes the upper bound (worst-case) growth rate. It answers: "As input size approaches infinity, how does the algorithm scale?"
| Notation | Name | Example | 1K items | 1M items | Rating |
|---|---|---|---|---|---|
| O(1) | Constant | Array access by index | 1 | 1 | โญโญโญโญโญ |
| O(log n) | Logarithmic | Binary Search | ~10 | ~20 | โญโญโญโญโญ |
| O(n) | Linear | Linear Search, Single loop | 1K | 1M | โญโญโญโญ |
| O(n log n) | Linearithmic | Merge Sort, Quick Sort | ~10K | ~20M | โญโญโญ |
| O(nยฒ) | Quadratic | Bubble Sort, Nested loops | 1M | 1T | โญโญ |
| O(2โฟ) | Exponential | Recursive Fibonacci | 2ยนโฐโฐโฐ | ๐ | โญ |
| O(n!) | Factorial | TSP brute force | 1000! | ๐๐ | โ ๏ธ |
๐ Growth Rate Visualization
Input Size (n) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
O(1): โ (flat line - perfect!)
O(log n): โโโ (grows very slowly)
O(n): โโโโโโโโโโโโโโโโโโโโโโโโ (steady growth)
O(nยฒ): โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ (๐)
O(2โฟ): โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ (๐ฅ)
๐งฎ How to Calculate Time Complexity
Rule 1: Drop Constants
// O(2n) โ O(n) โ we drop the constant 2
for ($i = 0; $i < count($arr); $i++) { echo $arr[$i]; }
for ($i = 0; $i < count($arr); $i++) { echo $arr[$i]; }
Rule 2: Drop Non-Dominant Terms
// O(nยฒ + n) โ O(nยฒ) โ nยฒ dominates as n grows
for ($i = 0; $i < $n; $i++) { // O(n)
for ($j = 0; $j < $n; $j++) { // O(nยฒ)
echo $i + $j;
}
}
Rule 3: Different Inputs โ Different Variables
// O(a + b), NOT O(2n)
function process(array $a, array $b) {
foreach ($a as $x) { /* ... */ } // O(len(a))
foreach ($b as $y) { /* ... */ } // O(len(b))
}
Rule 4: Add for Sequential, Multiply for Nested
// Sequential: O(n) + O(m) = O(n + m)
// Nested: O(n) * O(m) = O(n * m)
for ($i = 0; $i < $n; $i++) // O(n)
for ($j = 0; $j < $m; $j++) // O(m)
echo $i + $j; // Total: O(n * m)
๐ Analyzing Common Patterns
Pattern 1: Simple Loop โ O(n)
for ($i = 0; $i < $n; $i++) {
// constant work here
}
Pattern 2: Loop with Halving โ O(log n)
$i = $n;
while ($i > 1) {
$i = intdiv($i, 2); // i: n โ n/2 โ n/4 โ ... โ 1
// logโ(n) iterations
}
Pattern 3: Nested Loops โ O(nยฒ)
for ($i = 0; $i < $n; $i++)
for ($j = 0; $j < $n; $j++)
echo $i, $j; // n * n = nยฒ operations
Pattern 4: Two Pointers โ O(n)
$left = 0; $right = count($arr) - 1;
while ($left < $right) {
// Each iteration moves left forward OR right backward
$left++; // or $right--;
}
// Total iterations โค n, so O(n)
๐พ Space Complexity
Space complexity measures the extra memory an algorithm needs (excluding input storage).
O(1) Space โ In-Place
function sum(array $arr): int {
$total = 0; // only 1 variable
foreach ($arr as $x) $total += $x;
return $total;
} // O(1) space - only uses $total
O(n) Space โ New Array
function double(array $arr): array {
$result = []; // new array of size n
foreach ($arr as $x) $result[] = $x * 2;
return $result;
} // O(n) space - creates new array
๐ Best, Worst & Average Case
| Case | Meaning | Example: Linear Search |
|---|---|---|
| Best Case ฮฉ | Minimum time possible | ฮฉ(1) โ target is first element |
| Average Case ฮ | Expected time for random input | ฮ(n) โ check half the array |
| Worst Case O | Maximum time possible | O(n) โ target is last or not present |
Interview Tip: Unless specified otherwise, always discuss worst-case complexity. But if an algorithm has good average-case (like QuickSort), mention it!
๐ PHP Built-in Function Complexities
| Function | Time | Notes |
|---|---|---|
isset($arr[$key]) |
O(1) | Hash table lookup |
in_array($val, $arr) |
O(n) | Linear search |
array_search($val, $arr) |
O(n) | Linear search |
array_key_exists($key, $arr) |
O(1) | Hash lookup |
sort($arr) |
O(n log n) | Quicksort (PHP 8) |
array_push($arr, $val) |
O(1) | Amortized |
array_unshift($arr, $val) |
O(n) | Must reindex |
count($arr) |
O(1) | Stored internally |
๐งช Live Complexity Comparison
Let's compare O(n) vs O(nยฒ) with actual PHP code:
<?php
// O(n) - Linear
function sumArray(array $arr): int {
$sum = 0;
foreach ($arr as $x) $sum += $x; // n iterations
return $sum;
}
// O(nยฒ) - Quadratic (print all pairs)
function printAllPairs(array $arr): void {
$n = count($arr);
for ($i = 0; $i < $n; $i++) // n times
for ($j = 0; $j < $n; $j++) // n times each
echo "[{$arr[$i]},{$arr[$j]}] "; // nยฒ total
}
// Test with different sizes
$sizes = [10, 100, 1000, 10000];
foreach ($sizes as $n) {
$arr = range(1, $n);
$start = microtime(true);
sumArray($arr);
$linearTime = microtime(true) - $start;
echo "n=$n: O(n)=" . round($linearTime*1000, 4) . "ms\n";
// Try O(nยฒ) for smaller n only!
}
๐ผ Interview Questions
O(1) - Constant time. Arrays store elements in contiguous memory, so the address of any element can be calculated directly:
base_address + (index ร element_size).
O(log n). The loop variable doubles each time: 1, 2, 4, 8, 16, ..., n. This means it takes logโ(n) steps to reach n. This pattern appears in Binary Search and divide-and-conquer algorithms.
Amortized analysis averages the cost over a sequence of operations. Example: PHP's dynamic array (
$arr[] = $val) is usually O(1), but occasionally O(n) when it needs to resize. However, because resizes happen geometrically less often (double capacity each time), the amortized cost per push is still O(1).
โ ๏ธ Common Mistakes
โ Mistake: Saying O(2n) instead of O(n).
โ Fix: Drop constants. Big O describes growth rate, not exact operations.
โ Fix: Drop constants. Big O describes growth rate, not exact operations.
โ Mistake: Ignoring space complexity.
โ Fix: Always consider both time AND space. Sometimes you trade space for time (memoization).
โ Fix: Always consider both time AND space. Sometimes you trade space for time (memoization).
โ Mistake: Assuming nested loops are always O(nยฒ).
โ Fix: Check the loop bounds.
โ Fix: Check the loop bounds.
for(i=0;i<n;i++) for(j=0;j<5;j++) is O(n), not O(nยฒ).โ Mistake: Forgetting that
โ Fix: Use
in_array() is O(n).โ Fix: Use
isset($arr[$key]) for O(1) lookups. Know your language's built-in complexities.๐ Quick Quiz
๐ Complexity Cheat Sheet
| O(1) | Constant | Array access, Hash lookup, Math ops |
| O(log n) | Logarithmic | Binary Search, Balanced BST ops |
| O(n) | Linear | Single loop, Linear search |
| O(n log n) | Linearithmic | Merge Sort, Heap Sort, Quick Sort (avg) |
| O(nยฒ) | Quadratic | Bubble Sort, Nested loops |
| O(2โฟ) | Exponential | Recursive Fibonacci, Subset generation |
| O(n!) | Factorial | Permutation generation, TSP brute force |