Merge Sort

Divides the array in half, sorts each half, then merges them. Guaranteed O(n log n) performance regardless of input.

Best O(n log n) Avg O(n log n) Worst O(n log n) Space O(n) Stable Yes In-place No Comparison-based

How it works

Merge Sort divides the array in half, recursively sorts each half, then merges the two sorted halves into one. The merge step walks both halves with two pointers, always copying the smaller front element next.

The recursion depth is log n and each level does O(n) work to merge, giving a guaranteed O(n log n) regardless of input order.

Implementation

function mergeSort(arr, lo = 0, hi = arr.length - 1) {
  if (lo >= hi) return;
  const mid = Math.floor((lo + hi) / 2);
  mergeSort(arr, lo, mid);
  mergeSort(arr, mid + 1, hi);
  const left = arr.slice(lo, mid+1);
  const right = arr.slice(mid+1, hi+1);
  let i = 0, j = 0, k = lo;
  while (i < left.length && j < right.length)
    arr[k++] = left[i] <= right[j] ? left[i++] : right[j++];
  while (i < left.length) arr[k++] = left[i++];
  while (j < right.length) arr[k++] = right[j++];
}

Advantages

  • Guaranteed O(n log n) on every input — no pathological cases.
  • Stable, which makes it the standard choice for sorting records by a secondary key.
  • Predictable and easy to parallelize or adapt to external (on-disk) sorting.

Disadvantages

  • Needs O(n) auxiliary memory for the classic implementation.
  • Not in-place, and slower than Quick Sort in practice on small in-memory arrays due to the extra copying.

When to use it

Reach for it when stability matters, when worst-case guarantees matter, or when sorting data larger than RAM via external merge passes.