Sorting · Stage 1 of 3
Comparison Sorting & Adjacent Sweeps
Order elements so global comparisons become adjacent checks
Foundations
Sorting arranges an array so nums[0] <= nums[1] <= ... <= nums[n - 1]. A comparison sort learns that order only by comparing two elements at a time, and none can beat O(n log n) comparisons in the worst case. Merge sort meets that bound: split the array in half, sort each half the same way, then merge the two sorted halves by repeatedly taking the smaller front element. One element alone is already sorted.
Split in half
Merge back up
8 values · 3 levels = log₂ 8 · each level merges all 8
Order is transitive: if every neighbor pair has nums[i] <= nums[i + 1], then every pair is in order. So once an array is sorted, many questions about all pairs need only neighbors. Equal values sit side by side, and the two closest values are always adjacent. One sweep over the n - 1 neighbor pairs, O(n), replaces checking all n(n - 1) / 2 pairs.
Merge sort splits nums = [7, 1, 5, 3, 6] into [7, 1] and [5, 3, 6], sorts them into [1, 7] and [3, 5, 6], and merges those into [1, 3, 5, 6, 7]. To find the two closest values, checking every pair takes 10 comparisons. In sorted order only neighbors can be closest, so a sweep reads 4 gaps, 2, 2, 1, and 1: the closest values are 5 and 6.
nums, sorted
gap to next
- Open lesson
Two Pointers
The merge step walks two sorted lists with one pointer each.
Case Scenario
The problem
Sort an Array
Return nums sorted in non-decreasing order. Implement a real O(n log n) sort (merge or heap) — do not call the language sort if you can help it. Tests only check the result.
- Input
- nums = [5, 2, 3, 1]
- Output
- [1, 2, 3, 5]
Sort an Array asks for the comparison sort itself: return nums in increasing order in O(n log n) time without the built-in sort. Merge sort fits, because even its worst case is O(n log n). For nums = [5, 2, 3, 1], it splits into [5, 2] and [3, 1], sorts them into [2, 5] and [1, 3], and one merge gives [1, 2, 3, 5].
The direct approach is selection sort: find the smallest remaining element, swap it to the front, and repeat. Each pass rescans everything left, so n elements cost n(n - 1) / 2 comparisons: 6 here, and about 5 billion at n = 100,000. Nothing a pass learns about the order is kept, so the next pass compares the same elements again.
Approach 1 · Brute force
Selection sort
Pass i scans indexes i + 1 to n - 1 for the smallest value and swaps it into slot i. After the pass, slots 0 to i are final.
Time O(n²) · Space O(1)
- 1def sortArray(nums):
- 2 for i in range(len(nums)):
- 3 low = i
- 4 for j in range(i + 1, len(nums)):
- 5 if nums[j] < nums[low]:
- 6 low = j
- 7 nums[i], nums[low] = nums[low], nums[i]
- 8 return nums
Approach 2 · Merge sort
Walkthrough
Same input, now one step at a time. Each frame highlights the line that runs and the values it changes.
- 1.If the array has one element or none, return it.
- 2.Split at
mid = len(nums) // 2and sort each half recursively. - 3.Merge: repeatedly append the smaller front element of the two halves.
- 4.When one half runs out, append the rest of the other.
Python
Sort an Array
- Input:
- nums = [5, 2, 3, 1]
- Output:
- [1, 2, 3, 5]
- 1def sortArray(nums):
- 2 if len(nums) <= 1:
- 3 return nums
- 4 mid = len(nums) // 2
- 5 left = sortArray(nums[:mid])
- 6 right = sortArray(nums[mid:])
- 7 merged = []
- 8 i = j = 0
- 9 while i < len(left) and j < len(right):
- 10 if left[i] <= right[j]:
- 11 merged.append(left[i])
- 12 i += 1
- 13 else:
- 14 merged.append(right[j])
- 15 j += 1
- 16 merged.extend(left[i:])
- 17 merged.extend(right[j:])
- 18 return merged
nums
Split at mid = 2. Sort the left half and the right half on their own, then merge them.
The Pattern
The invariant: every call returns its part of the array sorted, and merging two sorted runs yields a sorted run. Splitting stops at single elements, so about log₂ n levels of merging, each touching all n elements once, sort the whole array in O(n log n).
Check it against the walkthrough. [5, 2, 3, 1] split into [5, 2] and [3, 1], and each half came back sorted, [2, 5] and [1, 3]. The last merge compared front values three times, 2 with 1, 2 with 3, and 5 with 3, then appended the rest of [2, 5].
Selection sort compared 6 pairs and kept nothing. Merge sort keeps every sorted run it builds and compares only front elements, so each level costs O(n). Once the array is sorted, any question about pairs, such as duplicates or the smallest gap, becomes one O(n) sweep over neighbors.
Complexity
TimeO(n log n)
SpaceO(n)
Each level of recursion merges n elements in total, and halving gives log n levels, so time is O(n log n) in every case. The halves and merged lists hold O(n) elements at a time, plus O(log n) for the call stack.
Brute force
Selection sort
O(n²) time
O(1) space
This technique
Merge sort
O(n log n) time
O(n) space
n=100
n=1,000
n=10,000
Comparisons on a log scale. At 10,000 values merge sort does about 375 times less work.
When to use this in an interview
- You need the elements in order, or the prompt forbids the built-in sort.
- A question about all pairs, such as duplicates or the closest values, gets easier between neighbors.
- An
O(n log n)budget is fine, and a guaranteed worst case matters.
In production
Sort-merge joins in a database
When neither table has a useful index, PostgreSQL can join two tables by sorting both on the join key and walking them side by side: rows with equal keys end up adjacent, so matching them is one sweep instead of comparing every pair. When the rows outgrow work_mem, it sorts runs that fit in memory, writes them to disk, and merges the runs, the walkthrough's merge step at scale.
Where this breaks
Sorted neighbors answer a pair question only when you sorted by the value that question compares. Merge sort also needs O(n) extra memory; a sort that must stay in place wants heapsort instead.
Your turn
Solve it yourself
You have watched merge sort split, merge, and finish in O(n log n). Write it yourself on Sort an Array, then order numbers by a custom comparison in Largest Number, and sweep sorted neighbors in Can Attend Meetings.
- 1Solve it
Sort an Array
Guided · the problem you traced above
- 2Largest NumberOn your own · same pattern, no walkthrough
- 3Can Attend MeetingsOn your own · same pattern, no walkthrough
Up next · Stage 2 of 3
Two-Pointer Merge PassesCombine two sorted runs in a singleO(n + m) scan