Find the repeating and missing number
LeetCode ↗ Java source ↗ Edit this article ↗
Jump to code:
Problem
You are given an array arr of n integers that was meant to contain each value from 1 to n exactly once. One value x appears twice and, as a consequence, one value y is missing. Return {x, y}: the repeating number first, the missing number second.
Constraints: 2 ≤ n ≤ 10^5, 1 ≤ arr[i] ≤ n, exactly one value is duplicated and exactly one is absent.
Example 1
arr = [3, 1, 2, 5, 3]
answer = [3, 4]
3 occurs twice and 4 never occurs.
Example 2
arr = [2, 2]
answer = [2, 1]
The smallest possible input: 2 repeats, 1 is missing.
Approach 1: Brute force
Intuition. For every candidate value v from 1 to n, scan the array and count how many times v appears. A count of 2 marks the repeating number, a count of 0 marks the missing one. Stop once both are known.
Algorithm.
- For
v = 1 .. n: count occurrences ofvinarr. - If the count is
2,repeating = v; if it is0,missing = v. - Break when both are set; return
{repeating, missing}.
static int[] bruteForce(int[] arr) {
int n = arr.length, repeating = -1, missing = -1;
for (int v = 1; v <= n; v++) {
int count = 0;
for (int x : arr) if (x == v) count++;
if (count == 2) repeating = v;
else if (count == 0) missing = v;
if (repeating != -1 && missing != -1) break;
}
return new int[]{repeating, missing};
}
Complexity. Time O(n^2): up to n candidates, each a full scan. Space O(1).
Too slow for n = 10^5 (10^10 comparisons in the worst case).
Approach 2: Better, a frequency array
Intuition. Counting every value in one pass is what a frequency array does. Since the values are confined to 1 .. n, an int[n + 1] indexed by value is a perfect hash: bump freq[x] for each element, then look for the index with count 2 and the index with count 0.
Algorithm.
freq = new int[n + 1]; for eachxinarr,freq[x]++.- For
v = 1 .. n:freq[v] == 2gives the repeating value,freq[v] == 0the missing one.
static int[] better(int[] arr) {
int n = arr.length;
int[] freq = new int[n + 1];
for (int x : arr) freq[x]++;
int repeating = -1, missing = -1;
for (int v = 1; v <= n; v++) {
if (freq[v] == 2) repeating = v;
else if (freq[v] == 0) missing = v;
}
return new int[]{repeating, missing};
}
Complexity. Time O(n): two linear passes. Space O(n) for the frequency array.
This is fast and clear. The remaining challenge, and the reason the problem is marked hard, is doing it in constant extra space.
Approach 3: Optimal, two equations (sum and sum of squares)
Intuition. Compare the array with the ideal sequence 1 .. n. The array’s sum differs from 1 + 2 + ... + n by exactly x - y: it contains an extra x and lacks a y. Likewise the sum of squares differs by x^2 - y^2. That gives two equations in two unknowns:
S - Sn = x - y
S2 - S2n = x^2 - y^2 = (x - y)(x + y)
Divide the second by the first to get x + y, then solve: x = ((x - y) + (x + y)) / 2 and y = x - (x - y). Division is exact because x ≠ y, so x - y ≠ 0.
Algorithm.
Sn = n(n+1)/2,S2n = n(n+1)(2n+1)/6.- One pass to compute
S(sum) andS2(sum of squares) of the array, inlong. diff = S - Sn(that isx - y),sumXY = (S2 - S2n) / diff.x = (diff + sumXY) / 2,y = x - diff.
static int[] optimalMath(int[] arr) {
long n = arr.length;
long sn = n * (n + 1) / 2; // 1 + 2 + ... + n
long s2n = n * (n + 1) * (2 * n + 1) / 6; // 1^2 + 2^2 + ... + n^2
long s = 0, s2 = 0;
for (int v : arr) {
s += v;
s2 += (long) v * v;
}
long diff = s - sn; // x - y (x repeating, y missing)
long sumXY = (s2 - s2n) / diff; // x + y since x^2 - y^2 = (x - y)(x + y)
long x = (diff + sumXY) / 2;
long y = x - diff;
return new int[]{(int) x, (int) y};
}
Dry run on arr = [3, 1, 2, 5, 3], n = 5: Sn = 15, S2n = 55, S = 14, S2 = 9 + 1 + 4 + 25 + 9 = 48. diff = -1, sumXY = (48 - 55) / (-1) = 7, x = (-1 + 7) / 2 = 3, y = 3 - (-1) = 4. Answer [3, 4].
Complexity. Time O(n): a single pass. Space O(1).
Everything must be computed in long. For n = 10^5, S2n ≈ 3.3 × 10^14 and even n(n+1)(2n+1) is about 2 × 10^15, both far beyond int. The Java tests include n = 100000 precisely to catch an int slip.
Approach 4: Optimal, xor and bit bucketing
Intuition. Xor-ing all array values together with all of 1 .. n cancels every value that appears an even number of times. The correct values appear twice (once in the array, once in 1 .. n), the repeating x appears three times and the missing y once, so the result is x ^ y. That alone does not separate them, but any set bit of x ^ y is a bit where x and y differ. Pick the lowest such bit and split every number (array values and 1 .. n alike) into two buckets by that bit. Within each bucket all values again cancel in pairs except for one of x or y, so xor-ing each bucket yields the two numbers. A final count over the array tells which of the two is the duplicate.
Algorithm.
xr = arr[0] ^ ... ^ arr[n-1] ^ 1 ^ ... ^ n, which equalsx ^ y.bit = xr & -xr, the lowest set bit.- Xor the array values and the numbers
1 .. nintoone(bit set) orzero(bit clear). - Count how often
oneoccurs inarr: twice meansoneis the repeating number, otherwisezerois.
static int[] optimalXor(int[] arr) {
int n = arr.length, xr = 0;
for (int i = 0; i < n; i++) xr ^= arr[i] ^ (i + 1); // every value pairs off except x and y: xr = x ^ y
int bit = xr & -xr; // lowest bit where x and y differ
int zero = 0, one = 0;
for (int i = 0; i < n; i++) {
if ((arr[i] & bit) != 0) one ^= arr[i]; else zero ^= arr[i];
if (((i + 1) & bit) != 0) one ^= (i + 1); else zero ^= (i + 1);
}
int count = 0; // decide which bucket holds the repeating number
for (int v : arr) if (v == one) count++;
return count == 2 ? new int[]{one, zero} : new int[]{zero, one};
}
Complexity. Time O(n): three linear passes. Space O(1). No overflow is possible because xor never leaves the int range.
Which optimal approach should you reach for? The math one is shorter and more common in interviews, but it depends on exact long arithmetic: S2n is about 3.3 × 10^14 for n = 10^5 and 3.3 × 10^17 for n = 10^6, both inside long, yet the intermediate n * (n + 1) * (2n + 1) computed with n as an int already overflows for n just above 1000. The xor one is bulletproof against overflow and generalises to “two numbers appear once, everything else twice”.
Edge cases and pitfalls
n = 2.[1, 1]gives[1, 2],[2, 2]gives[2, 1]. Both methods handle these; the xor method’sbitis1 ^ 2 = 3, lowest bit1.- Repeating value is
nor missing value is1.[5, 2, 3, 4, 5]returns[5, 1]. The frequency array must have sizen + 1so indexnis valid. - Overflow in the math approach. Compute
nas alongbefore multiplying, and square each value as(long) v * v, notv * v. - Which is which in the xor approach. The buckets give
{x, y}in unknown order. The final counting pass resolves it; skipping it returns the two numbers possibly swapped. - Return order. The problem wants repeating first, missing second.
[3, 4], not[4, 3]. - Invalid input. If no value repeats (a permutation), the math approach divides by zero and the brute force returns
{-1, -1}. The problem guarantees exactly one duplicate, so none of the methods check for this.
Related problems
- Find missing number is the one-unknown version solved by a single sum or xor.
- Find the Duplicate Number finds only the repeated value, with a cycle-detection twist.
- Two Sum uses the frequency-map idea from approach 2 in its hash-map form.