On this page
Description
Every int is 32 bits, and some questions are easiest to answer at that level. Which number in this list appears only once? Is this number a power of two? Which of these 20 features are switched on? Each has an obvious answer with a hash set or a loop over values. Each also has a shorter answer that works on the bits directly, in O(1) extra space. This skill covers the core operations, XOR cancellation, bitmasks as sets, and the traps around negative numbers and shifts.
We'll go from simple to more technical:
- The pattern: AND, OR, XOR, shifts, and the tricks built from them (
x & (x - 1),x & -x). - A second flavor: an int as a set of up to 32 items.
- Where bits show up in production (flags, permissions, hashing, compact sets).
- What breaks it: negative numbers, shift distances, precedence, edge values.
The approach
Java
int singleNumber(int[] nums) { // every value appears twice except one
int result = 0;
for (int num : nums) {
result ^= num; // x ^ x == 0 and x ^ 0 == x
}
return result;
}
Python
def single_number(nums: list[int]) -> int: # every value appears twice except one
result = 0
for num in nums:
result ^= num # x ^ x == 0 and x ^ 0 == x
return result
XOR is commutative and associative, so the order doesn't matter: every pair cancels to 0 wherever its two copies sit, and only the lone value survives. The same cancellation finds the missing number in 0..n (XOR all indices with all values) and swaps two variables without a temporary. It does not cancel a value that appears three times (x ^ x ^ x == x); that needs per-bit counting (below).
The other identities worth knowing cold:
Java
x & (x - 1) // clears the lowest set bit: 12 (1100) -> 8 (1000)
x & -x // keeps only the lowest set bit: 12 (1100) -> 4 (0100)
n > 0 && (n & (n - 1)) == 0 // n is a power of two (exactly one bit set)
(x >> i) & 1 // reads bit i
Python
x & (x - 1) # clears the lowest set bit: 12 (1100) -> 8 (1000)
x & -x # keeps only the lowest set bit: 12 (1100) -> 4 (0100)
n > 0 and (n & (n - 1)) == 0 # n is a power of two (exactly one bit set)
(x >> i) & 1 # reads bit i
x & (x - 1) counts set bits in one step per 1 bit (Brian Kernighan's method). x & -x works because -x is ~x + 1 in two's complement: every bit above the lowest 1 is flipped, so only that bit survives the AND. With two lone values a and b among pairs, XOR-ing everything gives a ^ b; any 1 bit in it (say x & -x) is a bit where a and b differ, so splitting the numbers on that bit separates a from b.
n & 1 and n >> 1 equal n % 2 and n / 2 only for non-negative n: -7 % 2 is -1 (so n % 2 == 1 misses negative odd numbers) while -7 & 1 is 1, and -7 >> 1 is -4 (it rounds down) while -7 / 2 is -3 (it rounds toward zero).
A second flavor: a bitmask as a set
An int is a set of up to 32 small integers - bit i is 1 when i is in the set:
Java
mask | (1 << i) // add i
mask & ~(1 << i) // remove i (x ^ (1 << i) toggles it - it would add i if absent)
(mask & (1 << i)) != 0 // contains i? parentheses required
a | b, a & b, a & ~b // union, intersection, difference - one instruction each
Integer.bitCount(mask) // size
for (int mask = 0; mask < (1 << n); mask++) { // every subset of n items (n <= 30)
for (int i = 0; i < n; i++) {
if (((mask >> i) & 1) == 1) { /* item i is in this subset */ }
}
}
Python
mask | (1 << i) # add i
mask & ~(1 << i) # remove i (mask ^ (1 << i) toggles it - it would add i if absent)
(mask & (1 << i)) != 0 # contains i?
a | b, a & b, a & ~b # union, intersection, difference
mask.bit_count() # size (Python 3.10+)
for mask in range(1 << n): # every subset of n items
for i in range(n):
if (mask >> i) & 1:
pass # item i is in this subset
Subset enumeration visits 2^n masks - about a million for n = 20 - so it suits small n. When the question is about each bit position across many numbers, count per position instead: in "every value appears three times except one", each position's count of 1s is a multiple of 3 plus the lone value's bit, so count % 3 rebuilds the answer bit by bit.
Where you'll see it
Permission and feature flags packed into an int (flags | FLAG_X to set, flags & ~FLAG_X to clear, (flags & FLAG_X) != 0 to test); Unix file modes (chmod 755 is rwx = 4 + 2 + 1 for the owner, r-x = 4 + 1 for group and others); Java's EnumSet, which stores a set of up to 64 enum constants in a single long; BitSet and Bloom filters; IP subnet checks (address & netmask). Java's HashMap keeps a power-of-two table size so it can pick a bucket with hash & (size - 1) - which, unlike hash % size, is never negative for a negative hash code.
Which tool for which job?
| You need | Use |
|---|---|
| The one value appearing once (others twice) | XOR everything |
| Others appear three times | count each bit position mod 3 |
| Is n a power of two? | n > 0 && (n & (n - 1)) == 0 |
| The lowest set bit | x & -x |
| A set of up to 32 or 64 small items | an int or long bitmask |
| Every subset of every subset | submask enumeration, 3^n in total |
| The largest XOR of any subset | a linear (XOR) basis |
| Bucket from a hash code | Math.floorMod(h, n) |
Common mistakes
| Mistake | What happens | Do this instead |
|---|---|---|
n >>= 1 on a negative number | the loop never ends (-1 >> 1 is -1) | >>>, or n &= n - 1 |
1 << 32 in Java | equals 1, not 0 | 1L << i |
flags & MASK != 0 | precedence surprise (C) or a compile error (Java) | parenthesize |
Power-of-two check without n > 0 | 0 and MIN_VALUE pass | test n > 0 |
Math.abs(h) % n for a bucket | a negative bucket when h is MIN_VALUE | Math.floorMod(h, n) |
Check yourself
Try to answer before opening each one - recalling beats re-reading.
1. Why does XOR-ing every element find the value that appears once among pairs - and why doesn't it work when the others appear three times?
Show answer
XOR is order-independent, x ^ x == 0 and x ^ 0 == x, so every pair cancels and the lone value remains. Three copies XOR to the value itself (x ^ x ^ x == x), so they don't cancel; count each bit position instead and take count % 3.
2. What does n & (n - 1) do, and why does the power-of-two test also need n > 0?
Show answer
It clears n's lowest 1 bit. A power of two has exactly one 1 bit, so the result is 0. But 0 has no bits to clear and Integer.MIN_VALUE (only the sign bit set) also gives 0, and neither is a power of two - hence n > 0.
3. while (n != 0) { count += n & 1; n >>= 1; } - what happens for n = -1, and what are two fixes?
Show answer
It never terminates: >> copies the sign bit in, so -1 stays -1. Use n >>>= 1 (zeros shift in, 32 iterations), or n &= n - 1 (one iteration per 1 bit - also 32 for -1). Or call Integer.bitCount(n).
Key takeaways
- XOR cancels values that appear an even number of times, in any order - lone value, missing number, and (split on a differing bit) two lone values.
x & (x - 1)clears the lowest set bit;x & -xisolates it. Power-of-two tests needn > 0.- An int is a set of up to 32 small integers:
|adds,& ~removes,&tests, and masks 0 to 2^n - 1 enumerate subsets. >>keeps the sign,>>>fills zeros;& 1and>> 1match% 2and/ 2only for non-negative numbers.- Shift distances wrap (
1 << 32 == 1), and==/!=bind tighter than&- use1Land parentheses. - When value tricks fail, count each bit position (sign bit included).