DSA Notes
Master merge sort completely — the divide-and-conquer approach, step-by-step trace, formal correctness proof, recurrence relation solution, bottom-up vs top-down implementation, natural merge sort for nearly sorted data, counting inversions, and all comparison-based optimizations.
The Core Idea
Merge sort is based on a simple observation: merging two sorted arrays is easy and fast.
If you have two sorted arrays, you can merge them into one sorted array in O(n) time by always taking the smaller of the two front elements.
The divide-and-conquer strategy:
- Divide: Split the array in half
- Conquer: Recursively sort each half
- Combine: Merge the two sorted halves
Implementation — Bottom-Up (Iterative)
In-Place Merge (for sorted array portions)
Complexity Analysis
Time Complexity — Always O(n log n)
Recurrence: T(n) = 2T(n/2) + O(n)
Recursion Tree:
| Level 0: 1 problem of size n | n work |
| Level 1: 2 problems of n/2 | n work |
| Level 2: 4 problems of n/4 | n work |
| Level log n: n problems of 1 | n work |
| Total levels | log n |
| Work per level | n |
| Total | n × log n = O(n log n) |
This is always O(n log n) — best case, average case, worst case. There is no lucky input that causes less work.
Space Complexity — O(n)
Each merge step creates a temporary array. At any point, at most O(n) extra space is in use (the current merge level's temporary storage).
The recursion stack adds O(log n) space. Total: O(n) dominated by the merge arrays.
Why Merge Sort is Stable
The merge step uses left[i] <= right[j] — taking from the left array first when equal. This preserves the original order of equal elements.
| (3,'A') vs (3,'B'): 3<=3 | take (3,'A') from left first |
| (3,'C') vs (3,'B'): 3<=3 | take (3,'C') from left first |
| Result | [(3,'A'), (3,'C'), (3,'B'), (3,'D')] |
Application — Counting Inversions
An inversion is a pair (i, j) where i < j but arr[i] > arr[j]. The number of inversions measures how "unsorted" an array is.
Merge sort can count inversions in O(n log n) — a beautiful augmentation:
Natural Merge Sort — O(n) on Sorted Data
Standard merge sort ignores existing order. Natural merge sort exploits natural runs in the data:
Summary
Merge sort is the guaranteed O(n log n) algorithm:
| Property | Value |
|---|---|
| Best case | O(n log n) — always this |
| Average case | O(n log n) |
| Worst case | O(n log n) |
| Space | O(n) auxiliary |
| Stable | ✅ Yes |
| Adaptive | ❌ No (unless using Natural Merge Sort) |
Choose Merge Sort when:
- Stable sort is required
- Guaranteed O(n log n) worst case needed
- Sorting linked lists (no random access needed)
- External sorting (data larger than RAM — merge works chunk by chunk)
- Counting inversions
Consider Quick Sort over Merge Sort when:
- Memory is limited (Quick Sort: O(log n) space vs O(n))
- Cache performance matters (Quick Sort is more cache-friendly)
*Next Lesson: Quick Sort*
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Merge Sort — Complete Guide to the Guaranteed O(n log n) Stable Sort.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Data Structures & Algorithms topic.
Search Terms
data-structures-algorithms, data structures & algorithms, data, structures, algorithms, sorting, merge, sort
Related Data Structures & Algorithms Topics