Understanding how merge sort achieves linearithmic time through divide and conquer
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:
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!
Recursively divide the array into two halves until each subarray has only one element (base case - already sorted).
Sort the subarrays. Since arrays with 0 or 1 element are already sorted, the sorting happens during the merge step.
Merge two sorted subarrays into one sorted array by comparing elements from both arrays and placing them in order.
The array is always divided exactly in half:
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++];
}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.
At each level of recursion, the merge operation processes elements:
Unlike quicksort, merge sort always divides in half:
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.
| Algorithm | Best | Average | Worst | Space | Stable |
|---|---|---|---|---|---|
| Merge Sort | O(n log n) | O(n log n) | O(n log n) | O(n) | Yes |
| Quick Sort | O(n log n) | O(n log n) | O(n²) | O(log n) | No |
| Heap Sort | O(n log n) | O(n log n) | O(n log n) | O(1) | No |
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.
Merge sort is the preferred algorithm for sorting linked lists because it doesn't require random access. It can efficiently merge linked list nodes.
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.
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.
Merge sort is naturally parallelizable. Different processors can sort different halves independently, then merge the results, making it ideal for multi-core systems.
Always O(n log n) regardless of input order - predictable and reliable
Preserves relative order of equal elements - important for multi-criteria sorting
Needs additional memory for merging - trade-off for guaranteed performance
Doesn't require random access, ideal for sequential data structures