Skip to content
dsa450for five year olds

Searching & Sorting · 10 of 36

Find a pair with a given difference

Find two numbers in a list that are exactly a given distance apart.

Simple way
time O(n^2)
room O(1)
Clever way
time O(n log n)
room O(1)

The problem, simply

You get an unsorted array and a number n. Is there a pair of numbers, at two different positions, whose difference is exactly n? Return true or false.

The difference of a pair does not care about order: 80 and 2 are 78 apart either way. So a negative n means the same as its positive size.

A story to remember it

Picture it

arraysorted
01234gap 60183040100ji

Sorted, the numbers are 1, 8, 30, 40, 100. The pair 40 and 100 is exactly 60 apart.

  • answer

Examples

A normal case

In
arr = [5, 20, 3, 2, 50, 80], n = 78
Out
true

80 - 2 = 78.

Both fingers move

In
arr = [100, 8, 40, 1, 30], n = 60
Out
true

100 - 40 = 60. The walkthrough below finds it.

No pair

In
arr = [90, 70, 20, 80, 50], n = 45
Out
false

The gaps are multiples of 10, so none is 45.

Difference zero

In
arr = [1, 5, 5], n = 0
Out
true

The two 5s sit at different positions, so they count. For [1, 2, 3] and n = 0 the answer is false: a number cannot pair with itself.

Negative n

In
arr = [-3, 4, 9], n = -7
Out
true

4 and -3 are 7 apart. Use the size of n.

Way 1: the simple way

Check every pair of positions. If any two numbers are exactly n apart, say yes.

java
class Solution {
    public boolean findPair(int[] arr, int n) {
        long want = Math.abs((long) n);
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (Math.abs((long) arr[i] - arr[j]) == want) return true;
            }
        }
        return false;
    }
}

How long it takes: every pair once, O(n^2). Extra room: O(1).

Way 2: the clever way

Sort, then use two fingers that both walk right. This is different from the "two numbers that add up to" trick, where the fingers start at opposite ends. Here both start at the left, because we care about the gap between them.

  1. Sort the array. Take want = |n|.
  2. i = 0, j = 1.
  3. If i == j, move j (a number cannot pair with itself).
  4. If arr[j] - arr[i] == want, return true.
  5. If the gap is too small, move j right to widen it.
  6. If the gap is too big, move i right to shrink it.
  7. When j falls off the end, return false.

Two fingers walk right, widening or shrinking the gap

01 / 09

arraygiven
01234100840130
arraysorted
01234183040100

Sort first: [1, 8, 30, 40, 100]. We want two numbers that are exactly 60 apart.

want
60
  • looking now
  • checking
  • answer
  • rejected
  • ignored
java
import java.util.*;

class Solution {
    public boolean findPair(int[] arr, int n) {
        long want = Math.abs((long) n);
        Arrays.sort(arr);
        int i = 0, j = 1;
        while (j < arr.length) {
            if (i == j) { j++; continue; }        // never pair a number with itself
            long gap = (long) arr[j] - arr[i];
            if (gap == want) return true;
            if (gap < want) j++;                  // too close, widen
            else i++;                             // too far, shrink
        }
        return false;
    }
}

How long it takes: sorting is O(n log n), then each finger moves at most n times, O(n). Total O(n log n). Extra room: O(1) besides the sort.

Another way: a hash set

Walk the numbers once and remember what you have seen in a hash set, a bag where you can ask "is this number inside?" instantly. For each number x, ask whether x - want or x + want is already in the bag.

java
import java.util.*;

class Solution {
    public boolean findPair(int[] arr, int n) {
        long want = Math.abs((long) n);
        Set<Long> seen = new HashSet<>();
        for (int x : arr) {
            if (seen.contains(x - want) || seen.contains(x + want)) return true;
            seen.add((long) x);
        }
        return false;
    }
}

This takes O(n) time on average but O(n) extra room. It also handles n = 0 for free: the second 5 finds the first 5 in the bag. Pick it when time matters more than memory, and the sorting way when memory is tight.

Watch out for

  • A negative n. Use its size, Math.abs(n), or the fingers chase a gap that can never appear.
  • Starting the fingers at opposite ends, like in two sum. Then moving either finger shrinks the gap, so you cannot tell which way to go.
  • Overflow: arr[j] - arr[i] with values near two billion does not fit in an int. Do it in long.
  • Sorting changes the caller's array. Copy it first if that matters.

What interviewers ask next

  • Count all pairs with difference k (LeetCode 532, "K-diff Pairs"). Count each value with a hash map. For k > 0, count values x where x + k exists. For k = 0, count values that appear at least twice.
  • Return the pair, not just yes or no. Return arr[i] and arr[j] instead of true.
  • What if the array is already sorted? Then Way 2 is O(n) time and O(1) room.
  • Another O(n log n) way: after sorting, for each x binary search for x + want in the part to its right.

Remember this

Grown-up words: the two fingers are two pointers moving in the same direction (a sliding window over a sorted array), and the bag of numbers seen is a hash set.