Back to Benchmark

Merge Sort - O(n log n) Complexity

Understanding how merge sort achieves linearithmic time through divide and conquer

What is Merge Sort?

Merge Sort is a divide-and-conquer sorting algorithm that works by recursively dividing the array into halves, sorting each half, and then merging the sorted halves back together. It's a stable, predictable algorithm with guaranteed O(n log n) performance.

Key Characteristics:

  • Divide and Conquer: Breaks problem into smaller subproblems
  • Stable Sort: Preserves relative order of equal elements
  • Guaranteed O(n log n): Always O(n log n) regardless of input
  • Not In-Place: Requires O(n) extra space for merging

Think of it like organizing a deck of cards - split the deck in half, sort each half separately, then merge them back together in order!

How Does Merge Sort Work?

1. Divide the Array

Recursively divide the array into two halves until each subarray has only one element (base case - already sorted).

2. Conquer (Sort)

Sort the subarrays. Since arrays with 0 or 1 element are already sorted, the sorting happens during the merge step.

3. Merge Sorted Arrays

Merge two sorted subarrays into one sorted array by comparing elements from both arrays and placing them in order.

4. Logarithmic Depth

The array is always divided exactly in half:

Level 0: n elements → divide into 2 subarrays of n/2
Level 1: n/2 elements each → divide into 4 subarrays of n/4
Level 2: n/4 elements each → divide into 8 subarrays of n/8
...
Level log₂(n): 1 element per subarray (base case)
Total work: n elements × log₂(n) levels = O(n log n)
Interactive Merge Sort Visualization
Watch how merge sort divides and merges the array!

Code Example:

// Merge Sort - O(n log n) guaranteed
function mergeSort(arr, left, right) {
  if (left < right) {
    const mid = Math.floor((left + right) / 2);

    // Recursively sort left and right halves
    mergeSort(arr, left, mid); // Left half
    mergeSort(arr, mid + 1, right); // Right half

    // Merge the sorted halves
    merge(arr, left, mid, right);
  }
}

function merge(arr, left, mid, right) {
  const leftArr = arr.slice(left, mid + 1);
  const rightArr = arr.slice(mid + 1, right + 1);

  let i = 0, j = 0, k = left;

  // Merge by comparing elements
  while (i < leftArr.length && j < rightArr.length) {
    if (leftArr[i] <= rightArr[j]) {
      arr[k++] = leftArr[i++];
    } else {
      arr[k++] = rightArr[j++];
    }
  }

  // Copy remaining elements
  while (i < leftArr.length) arr[k++] = leftArr[i++];
  while (j < rightArr.length) arr[k++] = rightArr[j++];
}
Built-in Functions for Sorting
Most programming languages provide built-in sorting functions that often use merge sort or similar efficient algorithms:

JavaScript/TypeScript

array.sort() - O(n log n) - In-place sort
// Uses quicksort or similar (implementation-dependent)
array.sort((a, b) => a - b) - O(n log n) - Custom comparator
// Sort numbers: ascending order

Python

sorted(list) - O(n log n) - Returns new sorted list
// Uses Timsort (hybrid of merge sort and insertion sort)
list.sort() - O(n log n) - In-place sort
// Modifies list in place, returns None

Java

Collections.sort(list) - O(n log n) - Timsort
// For List collections, uses merge sort variant
Arrays.sort(array) - O(n log n) - Dual-pivot quicksort
// For arrays, uses quicksort variant

C++

std::sort(begin, end) - O(n log n) - Introsort
// Hybrid of quicksort, heapsort, and insertion sort
std::stable_sort() - O(n log n) - Stable sort
// Uses merge sort, preserves relative order
Why is Merge Sort O(n log n)?

1. Logarithmic Recursion Depth

The array is always divided exactly in half, creating a balanced binary tree of recursive calls with depth log₂(n). Each level processes all n elements.

2. Linear Work Per Level

At each level of recursion, the merge operation processes elements:

Level 0: Merge n elements → O(n)
Level 1: Merge n/2 + n/2 = n elements → O(n)
Level 2: Merge n/4 × 4 = n elements → O(n)
...
Each level: O(n) work
Total: O(n) × O(log n) levels = O(n log n)

3. Guaranteed Performance

Unlike quicksort, merge sort always divides in half:

Best case: O(n log n) - Always divides in half
Average case: O(n log n) - Always divides in half
Worst case: O(n log n) - Always divides in half
Predictable and reliable performance!

💡 Trade-off: Space Complexity

Merge sort requires O(n) extra space for merging, while quicksort uses O(log n) space. However, merge sort's guaranteed O(n log n) and stability make it preferred when these properties matter.

Time Complexity Comparison
AlgorithmBestAverageWorstSpaceStable
Merge SortO(n log n)O(n log n)O(n log n)O(n)Yes
Quick SortO(n log n)O(n log n)O(n²)O(log n)No
Heap SortO(n log n)O(n log n)O(n log n)O(1)No
Real-World Examples

📊 External Sorting

Merge sort is ideal for external sorting (sorting data too large for memory). It processes data in chunks, making it perfect for sorting large files on disk.

🔗 Linked List Sorting

Merge sort is the preferred algorithm for sorting linked lists because it doesn't require random access. It can efficiently merge linked list nodes.

📧 Stable Sorting Needs

When you need to sort by multiple criteria (e.g., sort by name, then by age), merge sort's stability preserves the order from previous sorts.

🎯 Predictable Performance

Systems requiring guaranteed O(n log n) performance use merge sort. Real-time systems and applications with strict performance requirements benefit from merge sort's predictability.

🔄 Parallel Processing

Merge sort is naturally parallelizable. Different processors can sort different halves independently, then merge the results, making it ideal for multi-core systems.

Key Takeaways
  • Merge sort is O(n log n) - guaranteed

    Always O(n log n) regardless of input order - predictable and reliable

  • Stable sorting algorithm

    Preserves relative order of equal elements - important for multi-criteria sorting

  • Requires O(n) extra space

    Needs additional memory for merging - trade-off for guaranteed performance

  • Perfect for linked lists and external sorting

    Doesn't require random access, ideal for sequential data structures

Practice Exercises
Test your understanding of merge sort with these exercises. Try to solve them yourself before checking the answers!