Mergesort: Sorting by Divide and Conquer

Mergesort is built on a simple insight: splitting a problem in half repeatedly until it's trivial, then carefully combining the results back up.

circle-info

Core idea: A single element is always sorted. Two sorted halves can be merged into one sorted whole efficiently. Therefore — split everything down to single elements, then merge back up.


How It Actually Works

Let's trace through sorting [38, 27, 43, 3] step by step.

Step 1 — Split all the way down

Keep halving until every subarray has one element:

[38, 27, 43, 3]
    /          \
[38, 27]     [43, 3]
  /    \       /   \
[38]  [27]  [43]   [3]

Single elements are trivially sorted. Now we work back up.

Step 2 — Merge pairs

To merge two sorted lists, use a two-pointer approach: always pick the smaller of the two front elements.

Merge [38] and [27]:
  Compare 38 vs 27 → take 27
  Nothing left to compare → take 38
  Result: [27, 38] ✓

Merge [43] and [3]:
  Compare 43 vs 3 → take 3
  Nothing left to compare → take 43
  Result: [3, 43] ✓

Step 3 — Merge the merged halves

The key insight is that the merge step costs at most n − 1 comparisons for two lists totalling n elements — because every comparison places exactly one element, and the last element needs no comparison at all.


Why the Merge Works

Two sorted lists always have their smallest remaining element at the front. So at each step you only need to look at two elements — the heads of each list — and take the smaller one. You never need to look further into either list.


Understanding the O(n log n) Complexity

This is where it gets interesting. Let's build the intuition from the ground up.

The recursion tree

Every time mergesort runs, it splits into two halves. We can draw this as a tree:

Work done per level

At level k there are 2ᵏ merge operations, each on a subarray of n/2ᵏ elements:

The 2ᵏ and 2ᵏ cancel — every level costs exactly O(n) work, regardless of which level it is.

Number of levels

How many times can you halve n before reaching 1? You're asking: how many times can you divide n by 2?

That's log₂ n levels.

Putting it together

Upper, Average, and Lower Bounds

The worst case for mergesort is when every merge step requires the maximum number of comparisons — this happens when the two halves interleave perfectly (no early exhaustion of either list).

At each of the lg n levels, we do at most n − 1 comparisons across all merges on that level. So total comparisons ≤ n lg n.

Worst case: O(n log n)

This is tight — mergesort hits this bound on adversarial inputs like perfectly interleaved sorted halves.


The Auxiliary Buffer Problem

Mergesort has one practical drawback with arrays: you cannot merge two halves of an array in-place safely.

Consider merging {4, 5, 6} and {1, 2, 3} packed side-by-side in one array:

The first element placed would overwrite position 0 with 1, destroying the 4 before it's been used. To avoid this, mergesort copies each half into a temporary buffer before merging back.

circle-exclamation

Implementation


Summary

Property
Mergesort

Worst case

O(n log n)

Average case

Θ(n log n)

Best case

Ω(n log n)

Space

O(n) auxiliary

Stable?

Yes

Best for

Linked lists, external sorting, guaranteed performance

circle-check

Last updated