Comprehensive theory, algorithmic patterns, templates, and problem catalog for Bitwise Operations and Bitmasks.
Bit manipulation operates directly on the binary representation of integers at hardware speed.
-
&(AND): 1 only if both bits are 1. -
|(OR): 1 if either bit is 1. -
^(XOR): 1 if bits differ (x ^ x = 0,x ^ 0 = x). -
~(NOT): Inverts all bits. -
<<(Left Shift): Multiplies by$2^k$ . -
>>(Right Shift): Divides by$2^k$ .
| Operation | Expression |
|---|---|
| Check if |
(n & (1 << k)) != 0 |
| Set |
`n |
| Clear |
n & ~(1 << k) |
| Toggle |
n ^ (1 << k) |
| Clear lowest set bit |
n & (n - 1) (Brian Kernighan's) |
| Isolate lowest set bit | n & (-n) |
| Check if power of 2 | n > 0 && (n & (n - 1)) == 0 |
Find the element appearing once when every other element appears twice.
int singleNumber(vector<int>& nums) {
int unique = 0;
for (int num : nums) {
unique ^= num;
}
return unique;
}int countSetBits(int n) {
int count = 0;
while (n) {
n &= (n - 1); // Clears the lowest set bit
count++;
}
return count;
}
// Or use compiler built-in: __builtin_popcount(n)Iterate over all subsets of a set of size
void iterateSubsets(int n) {
for (int mask = 0; mask < (1 << n); ++mask) {
for (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {
// Element i is included in this subset
}
}
}
}Pattern D: Binary Digit DP with Fibonacci State Space (Non-negative Integers without Consecutive Ones)
When counting binary configurations "11"):
-
Fibonacci Recurrence: Number of valid
$k$ -bit strings satisfies$f[k] = f[k-1] + f[k-2]$ with$f[0] = 1, f[1] = 2$ . -
MSB-to-LSB Prefix Branching:
- On bit
$k$ where$(n & (1 \ll k)) \ne 0$ , taking branch$0$ allows any valid$k$ -bit suffix$\implies \text{ans} += f[k]$ . - Taking branch
$1$ matches the prefix. IfprevBit == 1, break immediately (illegal prefix extension).
- On bit
-
Complexity:
$\mathcal{O}(\log N)$ time and$\mathcal{O}(1)$ space.
-
Operator Precedence: Bitwise operators have lower precedence than arithmetic/comparison operators! Always use parentheses:
(n & 1) == 0notn & 1 == 0. -
Shifting Beyond Bit Width: Shifting by
$\ge 32$ on 32-bitintis undefined behavior in C++. Use1LL << kfor 64-bit shifts. -
Signed Integer Negative Shifts: Bitwise operations on negative numbers can trigger implementation-defined sign extension. Prefer
unsigned intoruint64_twhen doing heavy bit manipulations.
| # | Title | Difficulty | Time | Space | Solution Link |
|---|---|---|---|---|---|
| 600 | Non-negative Integers without Consecutive Ones | Hard |
C++ | ||
| 691 | Stickers to Spell Word | Hard |
C++ | ||
| 810 | Chalkboard XOR Game | Hard |
C++ | ||
| 982 | Triples with Bitwise AND Equal To Zero | Hard |
C++ |