Skip to content
← All posts

Minimum Absolute Difference: Sorting and Adjacent Pairs

5 min read
leetcodeproblemeasyarrayssorting

Given an array of distinct integers arr, find all pairs of elements with the minimum absolute difference. Return a list of pairs [a, b] where a is less than b, sorted in ascending order by a.

This is LeetCode 1200: Minimum Absolute Difference, and it is a clean introduction to the pattern of sorting first, then scanning adjacent elements. The technique shows up in many problems that ask about closest values, smallest gaps, or nearest neighbors in a collection.

sorted array12345diff=1diff=1
After sorting, the minimum absolute difference is always between adjacent elements. Green cells form pairs with the minimum difference of 1.

Why this problem matters

Interview problems that ask about "minimum difference" or "closest pair" in an unsorted array are testing whether you recognize that sorting unlocks the answer. Without sorting, you would need to compare every pair, which takes O(n^2) time. With sorting, the minimum difference is guaranteed to appear between two neighbors, and you only need a single pass.

This pattern extends to problems like finding the two closest points on a number line, merging intervals, or detecting near-duplicates. Whenever a problem involves pairwise comparisons on values, sorting first almost always reduces the work.

The key insight

In a sorted array, the minimum absolute difference can only occur between adjacent elements. Why? If you pick two elements that are not adjacent, there is at least one element between them. That in-between element is closer to one of the two you picked, so its difference with that neighbor is smaller. This means you never need to look beyond adjacent pairs.

This reduces the problem to three steps: sort the array, scan adjacent pairs to find the minimum difference, then collect all pairs that match it.

The solution

def minimum_abs_difference(arr: list[int]) -> list[list[int]]:
    arr.sort()
    min_diff = float('inf')

    for i in range(1, len(arr)):
        min_diff = min(min_diff, arr[i] - arr[i - 1])

    result = []
    for i in range(1, len(arr)):
        if arr[i] - arr[i - 1] == min_diff:
            result.append([arr[i - 1], arr[i]])

    return result

Let's walk through what each piece does.

The first line sorts the array in place. This is the move that makes everything else possible. Once the values are in order, the minimum absolute difference must live between two neighbors.

The first loop finds the minimum difference. It walks through every adjacent pair and tracks the smallest gap seen so far. Because the array is sorted, arr[i] - arr[i - 1] is always non-negative, so we do not need abs().

The second loop collects the answer. It walks through the pairs again and appends every pair whose difference equals the minimum. The pairs are automatically in ascending order by a because the array is sorted.

You can combine both passes into one by resetting your result list whenever you find a smaller difference. If the current difference equals the running minimum, append the pair. If it is strictly smaller, clear the list and start fresh with this pair. This approach uses a single loop instead of two, but the two-pass version is easier to read and reason about.

Visual walkthrough

Let's trace through arr = [4, 2, 1, 3] step by step. Watch how sorting transforms a scattered collection into an ordered sequence where the answer becomes obvious.

Step 1: Start with the unsorted input array.

arr4213

The input is [4, 2, 1, 3]. We cannot reason about minimum differences until the array is sorted.

Step 2: Sort the array.

sorted1234

After sorting: [1, 2, 3, 4]. The minimum absolute difference must now occur between adjacent elements.

Step 3: Scan adjacent pairs and compute differences.

sorted1234diffs111

Differences: |2-1|=1, |3-2|=1, |4-3|=1. The minimum difference is 1.

Step 4: Collect all pairs with the minimum difference.

sorted1234result[1,2][2,3][3,4]

All adjacent pairs have diff=1, so the answer is [[1,2],[2,3],[3,4]].

Every adjacent pair has a difference of 1, so all three pairs end up in the result. In cases where only some pairs match the minimum, the second pass filters out the rest.

Complexity analysis

ApproachTimeSpace
Sort + scanO(n log n)O(n)

Time is O(n log n), dominated by the sort. The two linear scans add O(n) each, but that does not change the overall bound. Sorting is the bottleneck.

Space is O(n) for the result list. In the worst case, every adjacent pair shares the same difference (like [1, 2, 3, 4]), so the result holds n - 1 pairs. The sort itself uses O(log n) auxiliary space in most implementations, which is smaller than the result.

The building blocks

1. Sort then scan adjacent pairs

arr.sort()
for i in range(1, len(arr)):
    diff = arr[i] - arr[i - 1]

This is the core pattern. Any time a problem asks about the minimum (or maximum) difference between elements, sorting and scanning neighbors is the go-to approach. You will see this in problems like "Contains Duplicate III" (LeetCode 220), "Minimum Distance Between BST Nodes" (LeetCode 783), and any problem where you need the closest pair of values.

2. Two-pass collect with a threshold

min_val = float('inf')
for x in data:
    min_val = min(min_val, compute(x))

results = [x for x in data if compute(x) == min_val]

The first pass finds the threshold, and the second pass collects everything that meets it. This pattern appears whenever a problem says "find all elements that share some optimal property." It separates the concern of finding the optimum from the concern of gathering the results, which keeps the logic clean and easy to verify.

Edge cases

  • Array of size 2: only one pair exists, and it is automatically the answer.
  • All elements equally spaced (like [1, 3, 5, 7]): every adjacent pair has the same difference, so all pairs appear in the result.
  • Large negative and positive values: sorting handles negatives correctly, and arr[i] - arr[i - 1] on a sorted array is always non-negative, so no abs() is needed.
  • Already sorted input: the sort is a no-op, and the scan proceeds normally. No special handling required.
  • Minimum difference of 0 is impossible: the problem states all integers are distinct, so adjacent differences are always at least 1.

From understanding to recall

You now know the full approach: sort, scan for the minimum gap, collect matching pairs. The logic is short and the idea is intuitive. But under interview pressure, small details trip people up. Do you scan from index 0 or 1? Do you need abs()? Do you collect pairs as [arr[i-1], arr[i]] or [arr[i], arr[i-1]]?

These are not conceptual gaps. They are recall gaps. Spaced repetition closes them. You practice writing the sort-and-scan loop from memory at increasing intervals. After a few rounds, the pattern is automatic. You see "minimum difference" in a problem statement, and the template flows out without hesitation.

Related posts

  • Sort an Array - The foundational sorting problem that teaches you to implement sorting from scratch
  • Contains Duplicate - Another problem where sorting (or hashing) transforms an O(n^2) brute force into an efficient scan
  • Merge Sorted Array - Practice working with sorted data and the two-pointer pattern that builds on sorting intuition

CodeBricks breaks Minimum Absolute Difference into its sort-then-scan and two-pass-collect building blocks, then drills them independently with spaced repetition. You type each piece from scratch until the pattern is automatic. When a sorting problem shows up in your interview, you do not think about it. You just write it.