How to recognise
numbers in pairs with one left over, counting or flipping bits, powers of two, adding binary strings, or "O(1) extra memory" over integers.
How to solve problems like this
- Write a few small inputs in binary and look at each bit column on its own.
- Pick the operation: xor cancels pairs, & tests or clears bits, | sets them, << and >> move them.
- Keep the answer in one integer and update it as you go, instead of keeping a set or a list.
- Check the edge cases: 0, a single number, the highest bit, and negative numbers in your language.
Variant: Bit by bit
The same, but take the number apart one bit at a time: look at the lowest bit, then shift the number so the next bit takes its place. Use it when something must be done with every bit, like counting the ones.
- Read the lowest bit with n & 1 and move to the next one with n >> 1.
- Do the work for each bit: count it, copy it into the answer, compare it with another number.
- n & (n - 1) clears the lowest 1 bit: loop on it to visit only the ones, or test a power of two with n & (n - 1) == 0.
- When every number appears three times but one, count the ones in each of the 32 positions; the positions whose count is not a multiple of 3 are the bits of the answer.
Where it's used
- File permissions in Unix. Read, write and run are three bits, so chmod 755 is three groups of three bits. To check a permission, the system takes its bit with a mask.
- RAID 5. Along with the data, RAID 5 stores its XOR. If one disk dies, the XOR of what is left restores it: everything except the lost data cancels out.
- Search engines. Lucene and Apache Spark store sets of document numbers as bitmaps (Roaring Bitmaps). Intersecting two sets is a bitwise AND, 64 numbers per operation.