Quick Overview
XOR cancels a value against itself, so `1 ^ 1 = 0`. That one property isolates the single unpaired number in an array using `O(1)` space and no hash map at all.
All computer data is stored in binary bits (0 and 1). Bit Manipulation applies bitwise logic directly on integer bits in O(1) instant execution time with zero memory overhead.
| Operator | Name | Logic Rule |
|---|---|---|
a & b | AND | 1 only if both bits are 1 |
| **`a | b`** | OR |
a ^ b | XOR | 1 if bits are different (1 ⊕ 0 = 1, 1 ⊕ 1 = 0) |
~a | NOT | Inverts all bits |
a << k | Left Shift | Multiplies by 2^k (5 << 1 == 10) |
a >> k | Right Shift | Divides by 2^k (10 >> 1 == 5) |
// Trick 1: Check if Number is Power of Two in O(1)
function isPowerOfTwo(n) {
return n > 0 && (n & (n - 1)) === 0;
}
console.log(isPowerOfTwo(16)); // Output: true (16 is 10000_2, 15 is 01111_2 -> 16 & 15 == 0)
console.log(isPowerOfTwo(18)); // Output: false
// Trick 2: Find the Single Non-Duplicate Number using XOR
// Rule: x ^ x = 0 and x ^ 0 = x (Duplicates cancel out!)
function singleNumber(nums) {
let result = 0;
for (const num of nums) {
result ^= num;
}
return result;
}
console.log(singleNumber([4, 1, 2, 1, 2])); // Output: 4 (1^1=0, 2^2=0 -> 4 remains)
// Trick 3: Count Set Bits (Hamming Weight / Brian Kernighan's Algorithm)
function countSetBits(n) {
let count = 0;
while (n > 0) {
n &= (n - 1); // Clears the lowest set bit in O(1)
count++;
}
return count;
}
console.log(countSetBits(11)); // Output: 3 (11 is 1011_2 in binary)
An integer can represent a set of up to 32 boolean flags:
i: mask |= (1 << i)i: mask &= ~(1 << i)i: (mask & (1 << i)) !== 0n & 1 === 0 is evaluated as n & (1 === 0)! Always wrap bitwise operations in parentheses: (n & 1) === 0.Congratulations! You have completed all 30 foundational Data Structures & Algorithms Core Patterns Learning Bytes, mastering everything from Big O analysis, sliding windows, and linked lists to binary search trees, Dijkstra's algorithm, dynamic programming, and bit manipulation!
Big O describes how work grows, not how long it takes. An `O(N^2)` algorithm on 1,000 items does a million steps; the same work at `O(N log N)` does about 10,000.
A dynamic array doubles rather than growing by one, so the expensive copy lands on the 1st, 2nd, 4th and 8th push. Averaged across every push, that is `O(1)` amortised.
A nested loop tests every pair in `O(N^2)`. On sorted data, moving two pointers inward from both ends rules out half the remaining candidates at each step and settles it in one `O(N)` pass.