"Under every integer is a row of bits. A fixed-width machine integer lets the CPU chew through that row almost in one bite and fold a whole flag set into one number. Python integers can grow across many machine words, though, so the magic is real—not infinitely free."
The Operators
Bitwise operations act on the binary representation directly: AND (&) keeps bits set in both operands, OR (|) keeps bits set in either, XOR (^) keeps bits that differ, NOT (~) flips every bit, and the shifts (<<, >>) slide bits left or right (a left shift by 1 multiplies by 2). Each is a single, blazing-fast CPU instruction. They're the lowest-level tools in the whole quest, and a handful of patterns built from them show up constantly.
The Tricks Worth Knowing
- Power-of-two check:
n & (n - 1) == 0is true exactly when n has a single set bit — i.e. n is a power of 2. (Subtracting 1 flips the lowest set bit and everything below it.) - Count set bits / clear the lowest one:
n & (n - 1)removes the lowest set bit; loop until zero to count bits. - XOR's magic:
a ^ a == 0anda ^ 0 == a. So if every element appears twice except one, XOR-ing them all cancels the pairs and leaves the loner — found in O(n) time and O(1) space, no hash set needed.
The Bitmask: a Set in One Integer
A fixed-width 64-bit integer can hold 64 flags. Python can represent wider masks, but operation cost grows with their width. Bitmask DP encodes subset state compactly; the familiar ~20-item limit is a workload-dependent rule of thumb, not a universal boundary.
The Readability Caveat
Bit tricks are seductive and can make code unreadable fast — a clever one-liner that takes ten minutes to decode is usually the wrong call. Reach for bit manipulation when it genuinely matters: a hot inner loop where constant factors count, flags and permission sets, or bitmask DP where it's the natural representation. Otherwise, prefer the clear version. Cleverness that no teammate (or future-you) can read is a cost, not a flex.