🧠 Data Structures & Algorithms · Advanced

Merge sort & quicksort in Java

Divide and conquer, stability, worst cases.

🧩 The mysteryTwo people can sort a deck faster than one: each sorts half, then they deal the piles together. That simple trick takes sorting from O(n²) to O(n log n).

Divide and conquer

Merge sort: split the array in half, sort each half recursively, then merge the two sorted halves. Halving gives log n levels, and each level does n work merging, so it's O(n log n) every time: best, average and worst case.

The merge step

Merging compares the heads of two sorted halves and takes the smaller each time. Using <= means ties take from the left half first, so equal elements keep their order: merge sort is stable. When one half runs out, copy whatever is left of the other.

while (i < l.length && j < r.length)
    out[k++] = l[i] <= r[j]
        ? l[i++] : r[j++];
// then copy whatever is left over
🔮 Predict it

Don't forget the leftovers

What does this print?

int[] l = {2, 5}, r = {1, 3, 9};
int[] out = new int[5];
int i = 0, j = 0, k = 0;
while (i < l.length && j < r.length)
    out[k++] = l[i] <= r[j] ? l[i++] : r[j++];
while (i < l.length) out[k++] = l[i++];
while (j < r.length) out[k++] = r[j++];
System.out.println(Arrays.toString(out));
  1. [1, 2, 3, 5, 9]
  2. [1, 2, 3, 5, 0]
  3. [2, 5, 1, 3, 9]
Show the answer

Round 1: 2 vs 1, take 1. Round 2: 2 vs 3, take 2. Round 3: 5 vs 3, take 3. Round 4: 5 vs 9, take 5. Now l is exhausted and the first loop stops; the leftover loop copies 9. Without it, the last slot would stay 0.

Quicksort: partition around a pivot

Quicksort picks a pivot, moves smaller items to its left and larger to its right, then recurses on each side. It sorts in place and is very fast in practice: O(n log n) on average, with a typical recursion depth of O(log n). It is not stable.

⚠️ The trap

The sorted-input disaster

Always picking the first element as pivot is fine on shuffled data. On already sorted input the pivot is always the smallest, so each partition splits into 0 and n - 1 items. That's n levels of about n work: O(n²). Random or median-of-three pivots make this very unlikely.

🤔 Think first

Merge or quick?

When would you choose merge sort over quicksort?

Think about it, then reveal the answer

When you need stability or a guaranteed O(n log n) worst case, and can spare O(n) extra memory. Quicksort's worst case is O(n²), but it's in place and usually faster for primitives, where stability doesn't matter.

💼 In the real world

Choosing in real systems

Merge sort's guarantees make it the backbone of Java's object sort, and of external sorting when data is bigger than memory. Quicksort variants dominate primitive sorting. Interviewers expect you to compare their worst cases, extra space and stability.

Key takeaways

  1. Merge sort: guaranteed O(n log n), stable, O(n) extra memory
  2. Quicksort: fast in practice, in place, not stable
  3. First-element pivot on sorted input gives O(n²)
  4. Random or median-of-three pivots make that very unlikely

💡 Merge sort is two people each sorting half a deck, then dealing the two piles together.

🤯 Did you know?

John von Neumann described merge sort in 1945. Tony Hoare invented quicksort in 1959 while working on machine translation as a visiting student in Moscow.

Practice questions

What does this print?

int[] l = {1, 4, 9}, r = {2, 3, 10};
int[] out = new int[6];
int i = 0, j = 0, k = 0;
while (i < 3 && j < 3)
    out[k++] = l[i] <= r[j] ? l[i++] : r[j++];
IO.println(k + " " + Arrays.toString(out));
  1. 5 [1, 2, 3, 4, 9, 0]
  2. 6 [1, 2, 3, 4, 9, 10]
  3. 5 [1, 2, 3, 4, 9, 10]
  4. 4 [1, 2, 3, 4, 0, 0]
Check your answer

5 [1, 2, 3, 4, 9, 0]. The loop takes the smaller head each time: 1, 2, 3, 4, 9. Then l is exhausted and the loop stops, leaving 10 uncopied and the last slot at 0.

Which input makes quicksort with 'always pick the first element as the pivot' degrade to O(n²)?

  1. A randomly shuffled array
  2. An array of distinct primes
  3. An already sorted array
  4. An array of length 1
Check your answer

An already sorted array. On sorted input the first element is the smallest, so every partition splits into 0 and n - 1 elements.

Next: so which one does Java use? Trick question: it uses two, and the choice depends on whether you sort ints or objects.