Skip to content

Coding patternsBlind 75

Missing Number

One number from 0 to n is missing from the list. Solved three ways, scanning for each number in O(n²), a hash set in O(n), and XOR in O(n) with O(1) memory, with a step-through, code in five languages and the Big O worked out from the code.

You are given an array nums of n different numbers. Each one is between 0 and n. There are n + 1 numbers in that range, so exactly one of them is not in nums. Return that number.

Example 1

Input: nums = [4, 0, 6, 1, 3, 2]

Output: 5

n = 6, so the range is 0 to 6. Every number in it shows up except 5.

0 to n
0123456
nums
400162133425

Example 2

Input: nums = [1, 0]

Output: 2

n = 2, so the range is 0 to 2. The missing number can be n itself.

Example 3

Input: nums = [1]

Output: 0

n = 1, so the range is 0 to 1. The missing number can be 0.

  • 1 ≤ n ≤ 10,000, where n is the length of nums
  • 0 ≤ nums[i] ≤ n, and all numbers in nums are different
Is nums sorted?
No. The numbers come in any order.
Can a number appear twice?
No. All n numbers are different, so exactly one number in the range is missing.
Can we change nums, or use extra memory?
The follow-up asks for O(1) extra memory and O(n) time, without changing nums.

The answer is the one number that appears once in “0 to n” but not in nums. Every other number appears in both. XOR cancels a number that appears twice (a ^ a = 0), so XOR-ing everything together leaves only the number that appears once. That is bit manipulation.

XOR O(n), O(1) space

XOR has two rules: a ^ a = 0 and a ^ 0 = a. The order does not matter.

Start with xor_total = nums_length. Then XOR in every index i from 0 to n − 1, and every value nums[i]. Together, nums_length and the indexes are every number from 0 to n, once each. The values are the same numbers with one missing. So every number except the missing one goes in twice and cancels. What is left in xor_total is the missing number.

The sum works the same way: 0 + 1 + … + n minus the sum of nums. XOR has the advantage that it can never overflow.

nums
400162133425
xor_total = 6
110
  1. xor_total = len(nums)
  2. for i in range(len(nums)):
  3. xor_total ^= i ^ nums[i]
  4. return xor_total

XOR has two rules: a ^ a = 0 and a ^ 0 = a. Start xor_total at len(nums) = 6, then XOR in every index and every value. Each number that is present shows up twice and cancels out.

1 / 8
Solution.javasolution.pySolution.cssolution.gosolution.ts
class Solution {
// XOR: every number in 0..n except the missing one goes in twice and cancels.
// One pass: O(n) time, O(1) memory.
public int missingNumber(int[] nums) {
int numsLength = nums.length;
// Start at numsLength, because the indexes only cover 0 to numsLength - 1.
int xorTotal = numsLength;
for (int i = 0; i < numsLength; i++) xorTotal ^= i ^ nums[i];
return xorTotal;
}
}
Time O(n)Space O(1)Here is how we get these from the code, in four steps.
  1. 1 Find the work that repeats

    The lit line does two XORs. That is 1 step. It sits inside one loop.

    1. xor_total = len(nums)
    2. for i in range(len(nums)):
    3. xor_total ^= i ^ nums[i]
    4. return xor_total
  2. 2 Count the runs on Example 1

    Example 1 has n = 6. The table shows xor_total after each run.

    6 runs.

    i012345
    xor_total after237525
    total
    6 runs
  3. 3 Write the count for any n

    The loop runs once per index:

    n runs

    Check it with Example 1: 6 runs, against 12 for the hash set and 24 for scanning.

  4. 4 Keep only the part that grows fastest

    There is nothing to drop. The count is already n.

    So the time is O(n).

  5. S Space: count the extra memory the same way

    The code keeps xor_total and i. The space is O(1).

    xor_totali

2,000 random arrays of 1 to 9 numbers, shuffled, with 0 or n missing about a third of the time. Scan for each number, hash set and XOR gave the same answer every time.

Largest inputsResult
10,000 numbers (the most allowed), shuffled, with 10,000 itself missing. XOR.Under 0.001 s, and under 0.001 MB of extra memory: just two numbers.
The same 10,000 numbers. Hash set.Under 0.001 s too, but about 0.6 MB for the set of all n values.
2,000 numbers. Scan for each number.0.04 s. At 10,000 numbers it would make up to 100 million checks.