Problem Overview
LeetCode 136 — Single Number — gives you a non-empty array of integers where every element appears exactly twice except for one element which appears exactly once. Your task is to find and return that single element. The problem carries two hard constraints: your solution must run in O(n) time and use only O(1) extra space.
These two constraints rule out the most intuitive approaches. A hash map or hash set that tracks counts runs in O(n) time but uses O(n) space. Sorting runs in O(1) extra space but costs O(n log n) time. The constraints force you toward a bit-level insight: XOR, a bitwise operation with exactly the properties needed to cancel pairs and expose the singleton.
Single Number is the canonical entry point into bit manipulation interview problems. It demonstrates that bitwise operators are not just low-level curiosities but powerful algorithmic tools that can replace entire data structures when the problem structure aligns with their mathematical properties.
- Input: non-empty integer array where every element appears twice except one
- Goal: find the element that appears exactly once
- Must run in O(n) time — no sorting allowed
- Must use O(1) extra space — no hash maps or sets
- Constraints: 1 <= nums.length <= 3*10^4; -3*10^4 <= nums[i] <= 3*10^4
- Each element in the array appears twice except for one element which appears only once
The XOR Solution
The XOR solution is elegant: initialize a variable result = 0, then XOR every element in the array into result. When you finish, result holds the single number. The entire solution is one line: return reduce(xor, nums) in Python or a simple loop with ^= in Java. No extra memory, no sorting, one pass.
Why does this work? XOR has two critical properties: a^a = 0 (any number XOR-ed with itself is zero) and a^0 = a (any number XOR-ed with zero is itself). Because XOR is also commutative and associative, the order of operations does not matter. Every pair of identical elements XORs to 0, and 0 XOR-ed with the unique element leaves the unique element.
Concretely: XOR-ing the entire array is equivalent to computing pair1^pair1 ^ pair2^pair2 ^ ... ^ single = 0 ^ 0 ^ ... ^ single = single. The pairs vanish and the singleton survives. This is why XOR is sometimes called a self-inverse operation — it undoes itself on repeated elements.
XOR Is the Perfect Operation for "Find the Odd One Out" Problems
XOR is the perfect operation for "find the odd one out" problems: it is commutative (a^b = b^a), associative ((a^b)^c = a^(b^c)), and self-inverse (a^a = 0). These three properties make duplicates vanish automatically. Because order does not matter and pairs cancel to zero, you can XOR elements in any sequence and the singleton will always remain. No hash map, no sort — just one accumulator.
Why XOR Works
XOR (exclusive OR) is a bitwise operation that outputs 1 for each bit position where the two input bits differ, and 0 where they are the same. At the integer level, XOR combines all bit positions independently. The properties that make it useful for Single Number emerge directly from this per-bit behavior.
Self-inverse: a^a = 0 for every integer a, because every bit position of a matches itself, producing 0. Identity: a^0 = a for every integer a, because 0 contributes no differing bits. Commutativity: a^b = b^a because bit comparison is symmetric. Associativity: (a^b)^c = a^(b^c) because each bit position is computed independently.
When you XOR every element of the array together, the commutative and associative laws let you mentally reorder the computation so that each duplicate pair is adjacent. Every adjacent pair cancels to 0. Chaining all those zeros together and XOR-ing the unique element with 0 gives you the unique element. The math is: result = 0 XOR x1 XOR x1 XOR x2 XOR x2 XOR ... XOR single = single.
- 1Property 1 — self-inverse: a ^ a = 0 (any integer XOR itself equals zero)
- 2Property 2 — identity: a ^ 0 = a (any integer XOR zero equals itself)
- 3Property 3 — commutative: a ^ b = b ^ a (order of operands does not matter)
- 4Property 4 — associative: (a ^ b) ^ c = a ^ (b ^ c) (grouping does not matter)
- 5Reorder all elements mentally: [x1, x1, x2, x2, ..., single]
- 6XOR of entire array = 0 ^ 0 ^ ... ^ 0 ^ single = single
Alternative Approaches
HashSet approach: iterate the array; if an element is not in the set, add it; if it is already in the set, remove it. At the end the set contains exactly one element — the single number. Time complexity O(n), space complexity O(n). This is intuitive but violates the O(1) space constraint of the problem.
Math approach: compute 2 * sum(set(nums)) - sum(nums). If every element appeared twice, 2*sum(set) would equal sum(nums). The difference is exactly the single number. Requires converting nums to a set to get unique values. Time O(n), space O(n) for the set. Clever but still uses extra space.
Sorting approach: sort the array, then scan pairs (nums[0],nums[1]), (nums[2],nums[3]), etc. The first pair that does not match has the single number at the first index. Time O(n log n), space O(1) or O(log n) depending on the sort algorithm. Violates the O(n) time constraint.
The Math Approach Is Clever But Still Requires O(n) Space
The math approach is clever: if all elements appeared exactly twice, the sum would be 2*sum(unique). The difference 2*sum(set(nums)) - sum(nums) reveals the single number. However, converting nums to a set creates an O(n) auxiliary data structure. This approach demonstrates creative use of algebra but does not meet the O(1) space constraint. It is worth mentioning in an interview to show you explored multiple angles before arriving at XOR.
Walk-Through Example
Consider nums = [4, 1, 2, 1, 2]. Initialize result = 0. XOR each element: 0^4 = 4, 4^1 = 5, 5^2 = 7, 7^1 = 6, 6^2 = 4. The final result is 4, which is the single number. Every other element (1 and 2) appeared twice and cancelled itself out.
Notice that the pairs do not need to be adjacent in the array. Commutativity and associativity mean the result is the same regardless of element order. You could shuffle [4, 1, 2, 1, 2] into any arrangement and still get 4. The XOR accumulator does not care about position — only about which values appear an odd versus even number of times.
For a single-element array nums = [7], the result is 0^7 = 7. The XOR of an array with one element is the element itself, which is the correct answer by definition. The algorithm handles this edge case naturally without any special-casing.
- 1Initialize: result = 0
- 2Step 1: result = 0 ^ 4 = 4
- 3Step 2: result = 4 ^ 1 = 5
- 4Step 3: result = 5 ^ 2 = 7
- 5Step 4: result = 7 ^ 1 = 6 (1 cancels its earlier contribution)
- 6Step 5: result = 6 ^ 2 = 4 (2 cancels its earlier contribution)
- 7Result = 4 — the single number; order is irrelevant due to commutativity
Code Walkthrough — Python and Java
Python one-liner using functools.reduce: from functools import reduce; from operator import xor; return reduce(xor, nums). This folds XOR across the entire list in a single expression. Alternatively, use an explicit loop: result = 0; for n in nums: result ^= n; return result. Both are O(n) time O(1) space.
Java explicit loop: public int singleNumber(int[] nums) { int result = 0; for (int n : nums) { result ^= n; } return result; } The ^= operator is XOR-assign. No imports needed, no extra data structures. The loop body is one line and the total method is five lines including braces.
Both implementations share the same structure: initialize an accumulator to 0, XOR every element into it, return the accumulator. The time complexity is O(n) because every element is visited exactly once. The space complexity is O(1) because only one integer variable is used regardless of input size.
This Only Works When Every Other Element Appears Exactly TWICE
This XOR approach only works when every other element appears exactly TWICE. If elements can appear three times (or any odd number > 1), XOR will not cancel them correctly — three XORs of the same value leaves the value itself (a^a^a = a). For three occurrences, use the bitwise state machine from Single Number II (LeetCode 137), which tracks bits through states 0 -> 1 -> 2 -> 0 using two accumulators (ones and twos).