🚀 Algorithm Complexity: Full Guide

1. What is Algorithmic Complexity?

Algorithmic complexity refers to how the performance (in terms of time and space) of an algorithm scales with input size n.

2. Time Complexity

Time complexity indicates the number of basic operations an algorithm performs. It is expressed using Big-O notation.

Common Time Complexities

NotationNameExample
O(1)ConstantAccessing array element
O(log n)LogarithmicBinary Search
O(n)LinearLoop through array
O(n log n)LinearithmicMerge Sort
O(n²)QuadraticNested loops
O(2ⁿ)ExponentialRecursive subset generation

Example:


for (let i = 0; i < n; i++) {
  for (let j = 0; j < n; j++) {
    console.log(i, j);
  }
}
// Time Complexity = O(n²)
  

3. Space Complexity

Space complexity refers to the memory used by the algorithm (excluding input size). It includes variables, function call stack, and data structures.


function sum(a, b) {
  let result = a + b;
  return result;
}
// Space Complexity: O(1)
  
Note: Recursive calls add to stack space.

4. Complexity Notations

5. How to Handle Large Inputs Efficiently

6. TLE (Time Limit Exceeded)

If your code exceeds the time limit of the online judge, it results in TLE. This often means the logic is right but inefficient.

Tip: Replace nested loops with prefix sums, binary search, or hash maps where possible.

7. Complexity Graph Behavior

8. How to Calculate Time Complexity (Step-by-Step)

  1. Break code into blocks (loops, recursions)
  2. Calculate time for each block
  3. Add or multiply depending on nesting

for (let i = 0; i < n; i++) {
  console.log(i);        // O(1)
}
// Total = O(n * 1) = O(n)
  

9. Types of Interview/Contest Questions

CategoryExample QuestionDifficulty
Loop AnalysisFind complexity of nested loopsEasy
RecursionFibonacci recursion complexityMedium
SortingCompare Merge and Bubble sortMedium
OptimizationReduce TLE using prefix sumHard
Space AnalysisRecursive vs iterative spaceMedium

10. Practice Examples

🔹 Example 1: Binary Search


function binarySearch(arr, target) {
  let left = 0, right = arr.length - 1;
  while (left <= right) {
    let mid = Math.floor((left + right) / 2);
    if (arr[mid] === target) return mid;
    else if (arr[mid] < target) left = mid + 1;
    else right = mid - 1;
  }
  return -1;
}
// Time: O(log n), Space: O(1)
  

🔹 Example 2: Brute Force Subarray Sum


let sum = 0;
for (let i = 0; i < n; i++) {
  for (let j = i; j < n; j++) {
    for (let k = i; k <= j; k++) {
      sum += arr[k];
    }
  }
}
// Time: O(n³) — highly inefficient
  

🔹 Optimized: Prefix Sum


// Preprocess
let prefix = Array(n+1).fill(0);
for (let i = 0; i < n; i++) {
  prefix[i+1] = prefix[i] + arr[i];
}

// Query sum of [i..j] = prefix[j+1] - prefix[i]