Skip to content

Appendix A: Complexity Cheat Sheet

A comprehensive reference for algorithm complexity analysis and common algorithm time/space complexities.

Big O Notation Hierarchy

From fastest to slowest:

NotationNameExamplen=10n=100n=1000
O(1)ConstantArray access, hash lookup111
O(log n)LogarithmicBinary search3710
O(n)LinearLinear search, array iteration101001,000
O(n log n)LinearithmicMerge sort, quick sort (avg)306649,966
O(n²)QuadraticBubble sort, nested loops10010,0001,000,000
O(n³)CubicMatrix multiplication1,0001,000,0001,000,000,000
O(2ⁿ)ExponentialRecursive Fibonacci1,0241.27×10³⁰
O(n!)FactorialTraveling salesman (brute force)3,628,800

Practical Limits (1 second execution)

ComplexityMaximum n
O(1)
O(log n)
O(n)~100,000,000
O(n log n)~10,000,000
O(n²)~10,000
O(n³)~500
O(2ⁿ)~25
O(n!)~11

Visual Complexity Growth Chart

Operations performed (y-axis) vs Input Size (x-axis)

n=10          n=100         n=1000        n=10000
│             │             │             │
│             │             │             │         O(n!)
│             │             │             │xxxxxxxxx
│             │             │ xxxxxxxxxxxx│
│             │ xxxxxxxxxxxx│             │
│ xxxxxxxxxxxx│             │             │         O(2^n)
│             │             │             │xxxxxxx
│             │             │ xxxxxxxxxxx│
│             │ xxxxxxxxxxx│             │
│ xxxxxxxxxxx│             │             │         O(n³)
│             │             │             │xxxxx
│             │             │ xxxxxxxxx  │
│             │ xxxxxxxxx  │             │
│ xxxxxxxxx  │             │             │         O(n²)
│             │             │      xxxx  │
│             │      xxx   │             │
│      xx    │             │             │         O(n log n)
│             │       xx   │        xx   │
│        x   │             │             │         O(n)
│         x  │          x  │           x │
│          x │             │             x         O(log n)
│xxxxxxxxxx ─┼─────────x ─┼────────────x┼─        O(1)
└────────────┴─────────────┴─────────────┴─────────

Legend: Lower = Better Performance

Complexity Comparison for n=100

Algorithm     Operations  Visualization
O(1)          1          █
O(log n)      7          ███
O(n)          100        ██████████
O(n log n)    664        ████████████████████████████████████
O(n²)         10,000     ████████████████████████████████████████████████████... (entire screen!)
O(2^n)        1.27×10³⁰  (larger than atoms in universe)

Key Insight: Even small differences in complexity class have MASSIVE impacts as input grows!

Practical PHP Examples by Complexity

O(1) - Constant Time:

php
<?php
# filename: constant-time-example.php

declare(strict_types=1);

// Direct array access
$value = $array[$key];  // Always same time

// Hash table operations
isset($cache[$key]);    // Instant lookup
unset($map[$key]);      // Instant delete

See: Chapter 4 (Arrays), Chapter 6 (Hash Tables)

O(log n) - Logarithmic:

php
<?php
# filename: logarithmic-example.php

declare(strict_types=1);

// Binary search on sorted array
$index = binarySearch($sortedArray, $target);

// Operations on balanced BST
$tree->search($value);  // Height = log n

See: Chapter 8 (Binary Search), Chapter 16 (Binary Search Trees)

O(n) - Linear:

php
<?php
# filename: linear-example.php

declare(strict_types=1);

// Single loop through array
foreach ($array as $item) {
    process($item);
}

// Linear search
$found = in_array($needle, $haystack);

See: Chapter 4 (Array Traversal), Chapter 7 (Linear Search)

O(n log n) - Linearithmic:

php
<?php
# filename: linearithmic-example.php

declare(strict_types=1);

// Efficient sorting
sort($array);           // PHP's built-in
$merged = mergeSort($array);  // Merge sort

See: Chapter 10-11 (Sorting Algorithms)

O(n²) - Quadratic:

php
<?php
# filename: quadratic-example.php

declare(strict_types=1);

// Nested loops
$count = count($arr);
for ($i = 0; $i < $count; $i++) {
    for ($j = $i + 1; $j < $count; $j++) {
        comparePair($arr[$i], $arr[$j]);
    }
}

See: Chapter 9 (Bubble Sort), Chapter 11 (Selection Sort)

O(2^n) - Exponential:

php
<?php
# filename: exponential-example.php

declare(strict_types=1);

// Naive recursive Fibonacci
function fib(int $n): int {
    if ($n <= 1) return $n;
    return fib($n-1) + fib($n-2);  // Two recursive calls
}

See: Chapter 25 (Dynamic Programming - shows optimization)

O(n!) - Factorial:

php
<?php
# filename: factorial-example.php

declare(strict_types=1);

// Generate all permutations
function permutations(array $items): array {
    if (count($items) <= 1) return [$items];
    
    $result = [];
    foreach ($items as $i => $item) {
        $rest = $items;
        unset($rest[$i]);
        foreach (permutations(array_values($rest)) as $perm) {
            $result[] = array_merge([$item], $perm);
        }
    }
    return $result;
}

See: Chapter 25 (Dynamic Programming - shows optimization)

Common Data Structure Operations

Array (PHP array with numeric keys)

OperationAverageWorstNotes
Access by indexO(1)O(1)Direct access
Search (unsorted)O(n)O(n)Linear scan
Search (sorted)O(log n)O(log n)Binary search
Insert at endO(1)O(1)$arr[] = $value
Insert at beginningO(n)O(n)array_unshift()
Insert at middleO(n)O(n)Shift elements
Delete at endO(1)O(1)array_pop()
Delete at beginningO(n)O(n)array_shift()
Delete at middleO(n)O(n)Shift elements

Hash Table (PHP associative array)

OperationAverageWorstNotes
AccessO(1)O(n)Key lookup
SearchO(1)O(n)isset(), array_key_exists()
InsertO(1)O(n)$arr[$key] = $value
DeleteO(1)O(n)unset($arr[$key])
IterationO(n)O(n)foreach

Stack (using SplStack or array)

OperationTimeNotes
PushO(1)$stack->push() or array_push()
PopO(1)$stack->pop() or array_pop()
PeekO(1)$stack->top() or end()
SearchO(n)Linear scan

Queue (using SplQueue or array)

OperationTimeNotes
EnqueueO(1)$queue->enqueue()
DequeueO(1)$queue->dequeue()
PeekO(1)Front element
SearchO(n)Linear scan

Binary Search Tree (Balanced)

OperationAverageWorst (unbalanced)
SearchO(log n)O(n)
InsertO(log n)O(n)
DeleteO(log n)O(n)
Min/MaxO(log n)O(n)

AVL Tree

OperationTimeSpaceNotes
SearchO(log n)O(1)Height bounded by 1.44 × log(n)
InsertO(log n)O(1)May require rotations
DeleteO(log n)O(1)May require rotations
Min/MaxO(log n)O(1)Height field per node
SpaceO(n)O(n)Strict balance maintained

Red-Black Tree

OperationTimeSpaceNotes
SearchO(log n)O(1)Height bounded by 2 × log(n)
InsertO(log n)O(1)Max 2 rotations
DeleteO(log n)O(1)Max 3 rotations
Min/MaxO(log n)O(1)Color bit per node
SpaceO(n)O(n)Looser balance than AVL

Comparison:

  • AVL: Stricter balance, faster searches, more rotations on insert/delete
  • Red-Black: Looser balance, faster insertions/deletions, slightly slower searches
  • Both guarantee O(log n) worst-case performance

See: Chapter 20 (Balanced Trees: AVL & Red-Black Trees)

Heap (SplPriorityQueue, SplMinHeap, SplMaxHeap)

OperationTime
InsertO(log n)
Extract min/maxO(log n)
Peek min/maxO(1)
Build heapO(n)
HeapifyO(log n)

Graph (Adjacency List)

OperationTimeSpace
Add vertexO(1)O(1)
Add edgeO(1)O(1)
Remove vertexO(V + E)-
Remove edgeO(E)-
Query edgeO(V)-

Sorting Algorithms

AlgorithmBestAverageWorstSpaceStableNotes
Bubble SortO(n)O(n²)O(n²)O(1)YesSimple, slow
Selection SortO(n²)O(n²)O(n²)O(1)NoAlways O(n²)
Insertion SortO(n)O(n²)O(n²)O(1)YesGood for small/nearly sorted
Merge SortO(n log n)O(n log n)O(n log n)O(n)YesPredictable, needs space
Quick SortO(n log n)O(n log n)O(n²)O(log n)NoFast average, in-place
Heap SortO(n log n)O(n log n)O(n log n)O(1)NoIn-place, not stable
Counting SortO(n + k)O(n + k)O(n + k)O(k)YesInteger keys only
Radix SortO(nk)O(nk)O(nk)O(n + k)YesInteger keys
Bucket SortO(n + k)O(n + k)O(n²)O(n)YesUniform distribution

PHP's sort() and usort(): O(n log n) average (uses quicksort variant)

Searching Algorithms

AlgorithmTimeSpaceNotes
Linear SearchO(n)O(1)Unsorted data
Binary SearchO(log n)O(1)Sorted data required
Jump SearchO(√n)O(1)Sorted data
Interpolation SearchO(log log n) avgO(1)Uniformly distributed
Hash Table LookupO(1) avgO(n)PHP arrays
Binary Search TreeO(log n) avgO(n)Balanced tree
Depth-First Search (DFS)O(V + E)O(V)Graph traversal
Breadth-First Search (BFS)O(V + E)O(V)Graph traversal

Graph Algorithms

AlgorithmTime ComplexitySpaceUse Case
DFSO(V + E)O(V)Traversal, cycles
BFSO(V + E)O(V)Shortest path (unweighted)
DijkstraO((V + E) log V)O(V)Shortest path (weighted)
Bellman-FordO(VE)O(V)Negative weights allowed
Floyd-WarshallO(V³)O(V²)All-pairs shortest paths
Prim'sO((V + E) log V)O(V)Minimum spanning tree
Kruskal'sO(E log E)O(V)Minimum spanning tree
Topological SortO(V + E)O(V)DAG ordering

String Algorithms

AlgorithmTimeSpaceUse Case
Naive String MatchO(nm)O(1)Simple pattern search
KMPO(n + m)O(m)Pattern matching
Boyer-MooreO(n/m) bestO(m)Fast pattern matching
Rabin-KarpO(n + m) avg, O(nm) worstO(1)Multiple patterns
Aho-CorasickO(n + m + z)O(m × σ)Multi-pattern search
Z-AlgorithmO(n + m)O(n + m)Fast pattern matching
Suffix ArrayO(n log n) build, O(m log n + occ) searchO(n)Substring queries
Suffix TreeO(n) build (Ukkonen's), O(m) searchO(n)Linear-time pattern matching
Longest Common SubsequenceO(nm)O(nm)Sequence comparison
Edit DistanceO(nm)O(nm)String similarity
Manacher's AlgorithmO(n)O(n)Palindrome finding

Notes:

  • Aho-Corasick: n = text length, m = total pattern length, z = number of matches, σ = alphabet size
  • Suffix Array: occ = number of occurrences, specialized algorithms can build in O(n)
  • Suffix Tree: Uses Ukkonen's algorithm for linear construction

Dynamic Programming Problems

ProblemTimeSpace
Fibonacci (naive)O(2ⁿ)O(n)
Fibonacci (DP)O(n)O(n)
Fibonacci (optimized)O(n)O(1)
0/1 KnapsackO(nW)O(nW)
Longest Common SubsequenceO(nm)O(nm)
Longest Increasing SubsequenceO(n²) or O(n log n)O(n)
Matrix Chain MultiplicationO(n³)O(n²)
Edit DistanceO(nm)O(nm)
Coin ChangeO(nA)O(n)

Stream Processing Algorithms

Stream processing algorithms handle continuous, potentially infinite data streams with constant or logarithmic space complexity.

AlgorithmTime per ElementSpaceNotes
Fixed-Size Sliding WindowO(1) add/sum/avg, O(n) min/maxO(n)Window size n
Optimized Sliding WindowO(1) amortized all opsO(n)Uses monotonic queues
Time-Based Sliding WindowO(1) add, O(n) cleanupO(n)n = events in window
Token Bucket Rate LimiterO(1)O(1)Constant space
Leaky Bucket Rate LimiterO(1)O(1)Constant space
Sliding Window CounterO(1)O(k)k = time buckets
Moving Average (SMA)O(1)O(n)n = window size
Exponential Moving Average (EMA)O(1)O(1)Constant space
Top-K ElementsO(1) add, O(n log n) queryO(n)n = unique elements
Reservoir SamplingO(1)O(k)k = sample size
Stream AggregatorO(1) per recordO(n)n = stored values

See: Chapter 36 (Stream Processing Algorithms)

Probabilistic Algorithms

Probabilistic algorithms trade perfect accuracy for dramatic space/time improvements, essential for big data processing.

AlgorithmTimeSpaceAccuracyUse Case
Bloom FilterO(k) add/containsO(m)No false negativesMembership testing
HyperLogLogO(1) addO(2^p)±0.81% (p=14)Cardinality estimation
Count-Min SketchO(d) add/estimateO(w×d)±εNFrequency estimation
Reservoir SamplingO(1) addO(k)Exact distributionRandom sampling
Morris CounterO(1) incrementO(1)±√nApproximate counting
Skip ListO(log n) avgO(n log n)ExactSorted set operations

Notes:

  • Bloom Filter: k = number of hash functions, m = bit array size
  • HyperLogLog: p = precision parameter (typically 14)
  • Count-Min Sketch: w = width, d = depth (hash functions)
  • Reservoir Sampling: k = sample size

See: Chapter 32 (Probabilistic Algorithms)

Concurrent Algorithms

Concurrent algorithms enable parallel execution, dramatically improving performance for I/O-bound and CPU-intensive tasks.

PatternTime ComplexitySpaceNotes
Async I/O (ReactPHP)O(1) schedulingO(n)n = concurrent operations
Parallel ProcessingO(n/p)O(n)p = processors
Coroutines (Swoole)O(1) yield/resumeO(k)k = coroutine stack
Worker PoolO(n/p)O(p)p = workers, n = tasks
Pipeline ProcessingO(n)O(k)k = pipeline stages
Fork-JoinO(n/p + log p)O(n)Divide and conquer

Notes:

  • Concurrent algorithms reduce wall-clock time but may increase total CPU time
  • Space complexity often increases due to multiple execution contexts
  • Actual speedup depends on I/O wait time and CPU cores available

See: Chapter 31 (Concurrent Algorithms)

Common PHP Function Complexities

Array Functions

FunctionTimeSpaceNotes
in_array()O(n)O(1)Linear search - avoid in loops
array_search()O(n)O(1)Linear search - returns key
isset()O(1)O(1)Hash lookup - use for membership
array_key_exists()O(1)O(1)Hash lookup - checks null values too
count()O(1)O(1)Stored value - cache outside loops
array_push()O(1)O(1)Append - same as $arr[] = $val
array_pop()O(1)O(1)Remove last
array_shift()O(n)O(1)Remove first, reindex - use SplQueue
array_unshift()O(n)O(1)Prepend, reindex - expensive
array_merge()O(n + m)O(n + m)Combine arrays
array_merge_recursive()O(n + m)O(n + m)Deep merge
array_combine()O(n)O(n)Keys + values to array
array_fill()O(n)O(n)Fill with value
array_pad()O(n)O(n)Pad to length
array_chunk()O(n)O(n)Split into chunks
array_column()O(n)O(n)Extract column from 2D array
array_flip()O(n)O(n)Swap keys and values
array_intersect()O(n * m)O(n)Common values
array_diff()O(n * m)O(n)Difference
array_values()O(n)O(n)Reindex numerically
array_keys()O(n)O(n)Extract keys
sort()O(n log n)O(log n)Quicksort variant
rsort()O(n log n)O(log n)Reverse sort
asort()O(n log n)O(log n)Sort maintaining keys
ksort()O(n log n)O(log n)Sort by keys
usort()O(n log n)O(log n)Custom comparison sort
array_unique()O(n)O(n)Hash-based deduplication
array_filter()O(n)O(n)Iterate + callback
array_map()O(n)O(n)Iterate + transform
array_reduce()O(n)O(1)Iterate + accumulate
array_walk()O(n)O(1)In-place modification
array_reverse()O(n)O(n)Reverse order
array_slice()O(k)O(k)Extract k elements
array_splice()O(n)O(k)Remove and replace
array_sum()O(n)O(1)Sum numeric array
array_product()O(n)O(1)Product of array
min() / max()O(n)O(1)Find min/max in array

String Functions

FunctionTimeSpaceNotes
strlen()O(1)O(1)Cached length
substr()O(k)O(k)Extract k characters
strpos()O(n)O(1)Find substring - fast
str_contains()O(n)O(1)PHP 8.0+ - check substring
str_starts_with()O(m)O(1)PHP 8.0+ - check prefix
str_ends_with()O(m)O(1)PHP 8.0+ - check suffix
str_replace()O(n)O(n)Simple replacement
str_ireplace()O(n)O(n)Case-insensitive replace
preg_match()O(n) avgO(1)Regex - can be O(2^n) worst
preg_replace()O(n) avgO(n)Regex replacement
explode()O(n)O(n)Split string
implode()O(n)O(n)Join strings
trim() / ltrim() / rtrim()O(n)O(n)Remove whitespace
strtoupper() / strtolower()O(n)O(n)Case conversion
strcmp()O(n)O(1)String comparison
levenshtein()O(n * m)O(n * m)Edit distance

PHP 8.0+ Modern Functions

FunctionTimeSpaceNotes
str_contains()O(n)O(1)Better than strpos() !== false
str_starts_with()O(m)O(1)Better than substr($str, 0, m)
str_ends_with()O(m)O(1)Better than substring comparison
array_is_list()O(n)O(1)Check if sequential numeric keys
fdiv()O(1)O(1)Division by zero returns INF
Match expressionO(1)O(1)Strict comparison switch

PHP 8.4+ Features

FeatureTimeSpaceNotes
Property hooksO(1)O(1)Overhead per property access
Asymmetric visibilityO(1)O(1)No performance impact
Typed class constantsO(1)O(1)Compile-time check
Override attributeO(1)O(1)Compile-time validation

SPL Data Structure Operations

OperationSplStackSplQueueSplHeapSplFixedArray
AccessO(1) topO(1) frontO(1) topO(1) by index
InsertO(1) pushO(1) enqueueO(log n)O(1) at index
DeleteO(1) popO(1) dequeueO(log n)O(1) at index
SearchO(n)O(n)O(n)O(n)
SpaceO(n)O(n)O(n)O(n) fixed

Example: When to use each:

php
<?php
# filename: queue-comparison.php

declare(strict_types=1);

// ❌ BAD: Using array_shift in loop (O(n²) total)
while (count($arr) > 0) {
    $item = array_shift($arr);  // O(n) each time
    process($item);
}

// ✅ GOOD: Using SplQueue (O(n) total)
$queue = new SplQueue();
foreach ($arr as $item) {
    $queue->enqueue($item);
}
while (!$queue->isEmpty()) {
    $item = $queue->dequeue();  // O(1) each time
    process($item);
}

Space Complexity Guide

Common Patterns

PatternSpaceExample
In-place algorithmO(1)Bubble sort, two pointers
Single array/variableO(n)Hash table, visited set
Two arraysO(n)Merge sort temp array
MatrixO(n²)Floyd-Warshall, DP table
Recursion depthO(n)DFS call stack
Complete binary treeO(2ⁿ)All subsets generation
Stream processingO(1) or O(log n)Sliding windows, aggregations
Probabilistic structuresO(1) to O(k)Bloom filters, sketches
Concurrent contextsO(p)p = parallel workers/threads

PHP-Specific Memory Considerations

php
<?php
# filename: memory-overhead.php

declare(strict_types=1);

// Array overhead
$arr = [];  // ~56 bytes base
$arr[] = 1; // ~72 bytes per element (with overhead)

// String memory
$str = '';  // ~24 bytes base
$str = 'hello';  // 24 + 5 bytes

// Object overhead
class Foo {}
$obj = new Foo();  // ~40 bytes minimum

Algorithm Selection Guide

Sorting

Small dataset (n < 100):

  • Insertion Sort O(n²) - Simple, efficient for small data

Medium dataset (100 < n < 1M):

  • Quick Sort O(n log n) - Fast average case
  • PHP's sort() - Optimized built-in

Large dataset (n > 1M):

  • Merge Sort O(n log n) - Predictable performance
  • Timsort (Python, Java) - Hybrid approach

Special cases:

  • Nearly sorted: Insertion Sort O(n)
  • Integer keys, small range: Counting Sort O(n + k)
  • Need stability: Merge Sort
  • Memory constrained: Heap Sort

Searching

Unsorted data:

  • Linear Search O(n) - Only option

Sorted data:

  • Binary Search O(log n) - Optimal

Frequent lookups:

  • Hash Table O(1) - Best average case
  • PHP associative array

Range queries:

  • Binary Search Tree O(log n)
  • Segment Tree O(log n)

Graph Traversal

Shortest path (unweighted):

  • BFS O(V + E)

Shortest path (weighted, non-negative):

  • Dijkstra O((V + E) log V)

Shortest path (negative weights):

  • Bellman-Ford O(VE)

All-pairs shortest path:

  • Floyd-Warshall O(V³)

Minimum spanning tree:

  • Prim's O((V + E) log V) - Dense graphs
  • Kruskal's O(E log E) - Sparse graphs

Optimization Techniques

Time Optimization

  1. Use appropriate data structure

    • Hash table for O(1) lookup
    • Heap for O(log n) min/max
  2. Avoid nested loops

    • O(n²) → O(n) using hash table
  3. Use binary search

    • O(n) → O(log n) for sorted data
  4. Memoization

    • O(2ⁿ) → O(n) for recursive problems
  5. Early termination

    • Break loops when answer found

Space Optimization

  1. In-place algorithms

    • Modify input instead of creating new array
  2. Two pointers

    • O(n) space → O(1) space
  3. Iterative vs recursive

    • O(n) stack space → O(1) space
  4. Sliding window

    • O(n) → O(k) where k is window size
  5. Rolling hash

    • O(m) → O(1) for pattern matching

Quick Reference: When to Use What

Need O(1) lookup?

→ Hash table (PHP array)

Need sorted data?

→ Binary Search Tree or sorted array

Need min/max quickly?

→ Heap (SplPriorityQueue)

Need FIFO?

→ Queue (SplQueue)

Need LIFO?

→ Stack (SplStack)

Need to find duplicates?

→ Hash table O(n)

Need to reverse?

→ Two pointers O(n), O(1) space

→ KMP O(n + m) or PHP strpos() O(n)

Need shortest path?

→ BFS (unweighted) or Dijkstra (weighted)

Need to sort?

→ PHP sort() O(n log n)

Need rate limiting?

→ Token Bucket O(1) time, O(1) space → Sliding Window Counter O(1) time, O(k) space

Need to track unique items in stream?

→ HyperLogLog O(1) add, O(2^p) space → Bloom Filter O(k) add/check, O(m) space

Need frequency counts in stream?

→ Count-Min Sketch O(d) add/estimate, O(w×d) space

Need parallel processing?

→ Worker Pool O(n/p) time, O(p) space → Async I/O O(1) scheduling, O(n) space

Common Mistakes to Avoid

  1. ❌ Using in_array() in loop → O(n²) ✅ Use hash table → O(n)

  2. ❌ Multiple array_shift() → O(n²) ✅ Use SplQueue → O(n)

  3. ❌ String concatenation in loop → O(n²) ✅ Use array + implode() → O(n)

  4. ❌ Nested foreach without thinking → O(n²) ✅ Consider hash table approach → O(n)

  5. ❌ Sorting already sorted data repeatedly ✅ Check if sorted first or maintain sorted order

  6. ❌ Using array_shift() in sliding window → O(n²) total ✅ Use deque or circular buffer → O(1) per operation

  7. ❌ Storing entire stream in memory → O(n) space ✅ Use stream processing algorithms → O(1) or O(log n) space

  8. ❌ Exact counting for billions of items → O(n) space ✅ Use probabilistic algorithms (Bloom filter, HyperLogLog) → O(1) or O(log n) space

Performance Testing Template

php
<?php
# filename: performance-testing.php

declare(strict_types=1);

function measureTime(callable $fn, mixed ...$args): float {
    $start = microtime(true);
    $fn(...$args);
    return microtime(true) - $start;
}

function measureMemory(callable $fn, mixed ...$args): int {
    $before = memory_get_usage();
    $fn(...$args);
    return memory_get_usage() - $before;
}

// Usage
$time = measureTime(fn() => myAlgorithm($data));
$memory = measureMemory(fn() => myAlgorithm($data));

echo "Time: " . number_format($time * 1000, 2) . " ms\n";
echo "Memory: " . number_format($memory / 1024, 2) . " KB\n";

Real-World Optimization Decisions

When to Optimize?

Don't optimize if:

  • Data size is small (n < 100)
  • Code runs rarely (batch jobs, migrations)
  • Code is clearer without optimization
  • Time saved is negligible

Do optimize if:

  • Data size is large (n > 10,000)
  • Code runs frequently (API endpoints, real-time systems)
  • User experience is affected (page load time)
  • Resource costs are high (server costs, memory)

Optimization Priority Matrix

Impact vs Effort

High Impact, Low Effort  ← START HERE
  ├─ Replace in_array() with isset()
  ├─ Cache count() outside loops
  ├─ Use native sort() instead of custom O(n²)
  └─ Enable OPcache

High Impact, High Effort  ← DO AFTER QUICK WINS
  ├─ Implement caching layer (Redis/Memcached)
  ├─ Database query optimization
  ├─ Algorithm redesign (e.g., O(n²) → O(n))
  └─ Data structure refactoring

Low Impact, Low Effort  ← DO IF TIME PERMITS
  ├─ Code style improvements
  ├─ Minor refactoring
  └─ Comment additions

Low Impact, High Effort  ← AVOID
  ├─ Micro-optimizations
  ├─ Premature optimization
  └─ Over-engineering

Real Production Examples

Example 1: E-commerce Product Search

php
<?php
# filename: product-search-optimization.php

declare(strict_types=1);

// ❌ BAD: O(n²) - checking duplicates in loop
$filtered = [];
foreach ($products as $product) {
    if (!in_array($product->id, $filtered)) {  // O(n) each time
        $filtered[] = $product->id;
    }
}
// With 10,000 products: 10,000² = 100M operations!

// ✅ GOOD: O(n) - using hash table
$seen = [];
$filtered = [];
foreach ($products as $product) {
    if (!isset($seen[$product->id])) {  // O(1) each time
        $filtered[] = $product->id;
        $seen[$product->id] = true;
    }
}
// With 10,000 products: 10,000 operations (10,000x faster!)

Impact: Page load reduced from 5s to 50ms

Example 2: User Activity Feed

php
<?php
# filename: activity-feed-optimization.php

declare(strict_types=1);

// ❌ BAD: N+1 query problem
$posts = $db->query("SELECT * FROM posts LIMIT 50");
foreach ($posts as $post) {
    $user = $db->query("SELECT * FROM users WHERE id = {$post['user_id']}");
    $post['author'] = $user;
}
// 51 database queries!

// ✅ GOOD: Single JOIN query
$posts = $db->query("
    SELECT posts.*, users.name, users.avatar
    FROM posts
    JOIN users ON posts.user_id = users.id
    LIMIT 50
");
// 1 database query (51x fewer queries!)

Impact: API response time reduced from 800ms to 15ms

Example 3: Log Processing

php
<?php
# filename: log-processing-optimization.php

declare(strict_types=1);

// ❌ BAD: String concatenation in loop
$log = '';
foreach ($entries as $entry) {
    $log .= $entry . "\n";  // Creates new string each time
}
// O(n²) time, O(n²) memory with 100,000 entries = 10B operations!

// ✅ GOOD: Array + implode
$lines = [];
foreach ($entries as $entry) {
    $lines[] = $entry;
}
$log = implode("\n", $lines);
// O(n) time, O(n) memory with 100,000 entries = 100K operations

Impact: Memory usage reduced from 5GB to 50MB

Cross-Reference Guide

By Chapter

Fundamentals:

  • Chapter 1: Introduction to Algorithms → Big O basics
  • Chapter 2: Time Complexity Analysis → Detailed complexity analysis
  • Chapter 3: Space Complexity → Memory usage patterns

Data Structures:

  • Chapter 4: Arrays and Lists → Array operations (this appendix)
  • Chapter 5: Stacks and Queues → Stack/Queue complexity
  • Chapter 6: Hash Tables → O(1) lookup patterns
  • Chapter 14: Heaps → Heap operations and Priority Queues
  • Chapter 16: Binary Search Trees → Tree operations
  • Chapter 17: Balanced Trees → AVL/Red-Black tree guarantees
  • Chapter 18: Tree Traversals → DFS/BFS complexity
  • Chapter 20: Balanced Trees (AVL & Red-Black) → Self-balancing tree operations

Algorithms:

  • Chapter 7: Linear Search → O(n) search
  • Chapter 8: Binary Search → O(log n) search
  • Chapter 9-13: Sorting Algorithms → Sorting comparison table
  • Chapter 19: Graph Representations → Graph storage complexity
  • Chapter 20-22: Graph Algorithms → DFS, BFS, Dijkstra complexity
  • Chapter 23: String Algorithms → Pattern matching complexity
  • Chapter 33: String Algorithms Deep Dive → Advanced string algorithms (Z-algorithm, Suffix Tree)
  • Chapter 25: Dynamic Programming → Memoization patterns
  • Chapter 31: Concurrent Algorithms → Parallel processing patterns
  • Chapter 32: Probabilistic Algorithms → Space-efficient data structures
  • Chapter 36: Stream Processing → Real-time algorithms

Optimization:

  • Chapter 29: Performance Optimization → Practical optimization
  • Appendix B: PHP Performance Tips → PHP-specific optimizations

By Problem Type

Need O(1) lookup? → Chapter 6: Hash Tables → This appendix: Hash Table section

Need to sort efficiently? → Chapter 10: Merge Sort → Chapter 12: Quick Sort → This appendix: Sorting Algorithms table

Need shortest path? → Chapter 20: BFS (unweighted) → Chapter 22: Dijkstra (weighted) → This appendix: Graph Algorithms table

Need to optimize recursive algorithm? → Chapter 25: Dynamic Programming → This appendix: DP Problems table

Working with strings? → Chapter 23: String Algorithms → Chapter 33: String Algorithms Deep Dive (advanced) → This appendix: String Algorithms table

Processing data streams? → Chapter 36: Stream Processing Algorithms → This appendix: Stream Processing Algorithms table

Need space-efficient solutions? → Chapter 32: Probabilistic Algorithms → This appendix: Probabilistic Algorithms table

Need parallel processing? → Chapter 31: Concurrent Algorithms → This appendix: Concurrent Algorithms table

Quick Decision Tree

Start: I need to process data

├─ Known operation on standard data?
│  └─ Use this appendix to find complexity

├─ Custom algorithm needed?
│  ├─ Search problem?
│  │  ├─ Sorted? → Chapter 8: Binary Search
│  │  └─ Unsorted? → Chapter 7: Linear Search
│  │
│  ├─ Sorting problem?
│  │  └─ Chapter 9-13: Sorting Algorithms
│  │
│  ├─ Graph problem?
│  │  └─ Chapter 19-22: Graph Algorithms
│  │
│  ├─ Optimization problem?
│  │  └─ Chapter 25: Dynamic Programming
│  │
│  ├─ Stream processing?
│  │  └─ Chapter 36: Stream Processing Algorithms
│  │
│  ├─ Big data / space constraints?
│  │  └─ Chapter 32: Probabilistic Algorithms
│  │
│  └─ Need parallel/concurrent?
│     └─ Chapter 31: Concurrent Algorithms

└─ Performance issue?
   ├─ Algorithm complexity? → This appendix
   ├─ PHP-specific? → Appendix B
   └─ Profiling needed? → Chapter 29

Resources

External References

This Series

  • Chapter 1: Introduction to Algorithms
  • Chapter 2: Time Complexity Analysis - Deep dive into Big O
  • Chapter 3: Space Complexity - Memory usage analysis
  • Chapter 4: Arrays and Lists - Array operations
  • Chapter 6: Hash Tables - O(1) data structures
  • Chapter 8: Binary Search - O(log n) searching
  • Chapter 10-13: Sorting Algorithms - Complete sorting guide
  • Chapter 25: Dynamic Programming - Optimization techniques
  • Chapter 29: Performance Optimization - Real-world optimization
  • Chapter 31: Concurrent Algorithms - Parallel processing patterns
  • Chapter 30: Real-World Case Studies - Practical algorithm applications
  • Chapter 32: Probabilistic Algorithms - Space-efficient data structures
  • Chapter 33: String Algorithms Deep Dive - Advanced string matching
  • Chapter 36: Stream Processing Algorithms - Real-time data processing
  • Appendix B: PHP Performance Tips - PHP-specific optimizations
  • Appendix C: Glossary - Algorithm terminology