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
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.
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.
- Sort the array. Take
want = |n|. i = 0,j = 1.- If
i == j, movej(a number cannot pair with itself). - If
arr[j] - arr[i] == want, returntrue. - If the gap is too small, move
jright to widen it. - If the gap is too big, move
iright to shrink it. - When
jfalls off the end, returnfalse.
Two fingers walk right, widening or shrinking the gap
01 / 09
Sort first: [1, 8, 30, 40, 100]. We want two numbers that are exactly 60 apart.
- want
- 60
- looking now
- checking
- answer
- rejected
- ignored
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.
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 anint. Do it inlong. - 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. Fork > 0, count valuesxwherex + kexists. Fork = 0, count values that appear at least twice. - Return the pair, not just yes or no. Return
arr[i]andarr[j]instead oftrue. - What if the array is already sorted? Then Way 2 is
O(n)time andO(1)room. - Another
O(n log n)way: after sorting, for eachxbinary search forx + wantin 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.