Master this topic with zero to advance depth.
Bit manipulation involves algorithmically manipulating bits (0s and 1s). It is highly efficient and forms the basis of many hardware-level optimizations.
| Operator | Symbol | Rule |
|---|---|---|
| AND | & | 1 & 1 = 1, otherwise 0. (Masking) |
| OR | ` | ` |
| XOR | ^ | 1 ^ 0 = 1, 1 ^ 1 = 0. (Toggling/Canceling) |
| NOT | ~ | Flips all bits. |
| Left Shift | << | |
| Right Shift | >> | (Arithmetic) |
n & (n - 1) removes the least significant bit that is 1.n & -n isolates the lowest bit set to 1.Think of a number as a collection of toggles. Bit manipulation allows you to flip, check, or set these toggles in time.
Single Number
Given a non-empty array of integers nums, every element appears twice except for one. Find that single one.
You must implement a solution with a linear runtime complexity and use only constant extra space.
Examples
Intuition
Count the frequency of each number using a hash map. The number with frequency 1 is the answer.
Intuition
By sorting the array, identical elements become adjacent. We can then iterate through the array in steps of 2. If an element is not equal to its successor, it's the single number.
Intuition
The XOR operator has two key properties: and . Since every number except one appears twice, XORing all elements together will cause the duplicates to cancel out, leaving only the single number.
Power of Two
Given an integer n, return true if it is a power of two. Otherwise, return false.
An integer n is a power of two if there exists an integer x such that .
Examples
Intuition
Keep dividing the number by 2 until it hits 1. If at any point the remainder is not 0, it's not a power of two.
Intuition
Since the input is a 32-bit signed integer, the largest power of two is . If n is a power of two, it must be a divisor of .
Intuition
A power of two in binary has exactly one bit set. The expression n & (n - 1) clears the rightmost set bit. If n is a power of two, clearing its only set bit should result in 0.
Single Number II
Given an integer array nums where every element appears three times except for one, which appears exactly once. Find the single element and return it.
You must implement a solution with a linear runtime complexity and use only constant extra space.
Examples
Intuition
The simplest way to track occurrences is using a hash map or frequency array. We count how many times each number appears and return the one with a count of 1.
Intuition
If we sort the numbers, identical numbers will be adjacent. We can jump in steps of 3 and check if nums[i] is different from nums[i+1].
Intuition
Every number that appears three times will contribute exactly 3 (or 0) to the sum of bits at any given position. If we sum the bits at each position and take modulo 3, the remaining bit belongs to the single number.
Single Number III
Given an integer array nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once. You can return the answer in any order.
You must write an algorithm that runs in linear runtime complexity and uses only constant extra space.
Examples
Intuition
The most intuitive approach is to use a hash map to count the frequency of each number and extract those with a count of 1.
Intuition
Sort the array to bring duplicates together. Iterate through the array; if current element is not equal to the next, it's a single number. Otherwise, skip two.
Intuition
XORing all numbers gives . Find the lowest set bit in this XOR sum to divide all numbers into two groups (where this bit is set vs. not set). XORing within each group isolates and .
Bitwise AND of Numbers Range
Given two integers left and right that represent the range [left, right], return the bitwise AND of all numbers in this range, inclusive.
Examples
Intuition
Iterate from left to right and perform bitwise AND on all numbers. This is slow if the range is large.
res = left.i from left + 1 to right.res &= i.res.Intuition
Shift both left and right rightward until they are identical. The bits that are removed are the ones that fluctuate within the range. Finally, shift the common prefix back to its original position.
Intuition
The bitwise AND of a range is the common prefix of the binary representations of the range's endpoints. Any bit that changes within the range will eventually become 0 in the final AND result.
right > left:
right = right & (right - 1) (clears the rightmost set bit).Detailed Dry Run
left=5(101), right=7(111) Iteration 1: right = 7 & 6 = 6 (110). 6 > 5. Iteration 2: right = 6 & 5 = 4 (100). 4 < 5. Stop. Result: 4
Number of 1 Bits
Write a function that takes an unsigned integer and returns the number of '1' bits it has (also known as the Hamming weight).
Examples
11 in binary is 1011, which has three '1' bits.
Intuition
The most straightforward way is to check each of the 32 bits one by one. We can do this by shifting the number right and checking the last bit using bitwise AND with 1.
count = 0.(n & 1) == 1.count.n >>= 1.count.Intuition
Most modern programming languages provide highly optimized built-in functions to count set bits, often utilizing specific CPU instructions like POPCNT.
Intuition
Instead of checking every bit, we can jump directly between set bits. The operation n & (n - 1) always clears the least significant set bit of .
count.Detailed Dry Run
n = 12 (binary 1100)
| Iteration | n (Before) | n-1 | n & (n-1) | count |
|---|---|---|---|---|
| 1 | 1100 (12) | 1011 (11) | 1000 (8) | 1 |
| 2 | 1000 (8) | 0111 (7) | 0000 (0) | 2 |
| Result: 2 |
Reverse Bits
Reverse bits of a given 32 bits unsigned integer.
Examples
43261596 (00000010100101000001111010011100) reversed is 964176192 (00111001011110000010100101000000).
Intuition
Iterate through each of the 32 bits of the input. In each step, shift the result left and add the last bit of the input. Then shift the input right.
res = 0.n: n & 1.res left and add that bit: (res << 1) + (n & 1).n by 1.res.Intuition
A 32-bit integer consists of 4 bytes. We can precompute or manually reverse the bits for each byte (8 bits) and then combine them. This is faster when multiple calls are made as the byte reversals can be cached.
Intuition
We can reverse the bits using a series of mask and shift operations. First, swap adjacent bits, then swap adjacent pairs, then adjacent nibbles (4 bits), and so on.
n = ((n & 0xAAAAAAAA) >>> 1) | ((n & 0x55555555) << 1)n = ((n & 0xCCCCCCCC) >>> 2) | ((n & 0x33333333) << 2)n = ((n & 0xF0F0F0F0) >>> 4) | ((n & 0x0F0F0F0F) << 4)n = ((n & 0xFF00FF00) >>> 8) | ((n & 0x00FF00FF) << 8)n = (n >>> 16) | (n << 16)Sum of Two Integers
Given two integers a and b, return the sum of the two integers without using the operators + and -.
Examples
Intuition
Simulate how a half-adder or full-adder works. Iterate through each bit position (0 to 31), calculate the sum of bits and the carry, and build the result bit by bit.
res = 0, carry = 0.i from 0 to 31:
a and b.sum = bitA ^ bitB ^ carry.carry = (bitA & bitB) | (carry & (bitA ^ bitB)).res to sum.res.Intuition
The iterative logic can be expressed recursively. The sum of a and b is equivalent to the XOR of a and b (sum without carry) plus the AND of a and b shifted left (the carry).
Intuition
Addition can be broken into two parts: the sum without carry (a ^ b) and the carry itself ((a & b) << 1). We repeat this process until the carry becomes zero.
a ^ b gives the sum bits where no carry is involved.a & b gives the bits where a carry is generated.Detailed Dry Run
a = 2 (10), b = 3 (11)
Missing Number
Given an array nums containing n distinct numbers in the range [0, n], return the only number in the range that is missing from the array.
Examples
n = 3. Range is [0,3]. 2 is missing.
n = 2. Range is [0,2]. 2 is missing.
Intuition
Sort the array and check if each index matches the value at that index. The first index where nums[i] != i is the missing number. If all match, the missing number is .
nums in ascending order.nums[i] != i, return i.n.Intuition
The sum of the first numbers is . By subtracting the sum of all elements in the array from this total sum, we obtain the missing number.
Intuition
XORing a number with itself results in 0 (). If we XOR all numbers in the range and all numbers in the array, every number present in the array will appear twice and cancel out, leaving only the missing number.
missing = n (or 0).missing ^= i ^ nums[i]missing.Detailed Dry Run
nums = [3, 0, 1], n = 3 missing = 3 i=0: missing = 3 ^ 0 ^ 3 = 0 i=1: missing = 0 ^ 1 ^ 0 = 1 i=2: missing = 1 ^ 2 ^ 1 = 2 Result: 2
Count Triplets That Can Form Two Arrays of Equal XOR
Given an array of integers arr. We want to select three indices i, j and k where (0 <= i < j <= k < arr.length).
Let a = arr[i] ^ ... ^ arr[j - 1] and b = arr[j] ^ ... ^ arr[k]. Return the number of triplets (i, j, k) such that a == b.
Examples
Intuition
Iterate through all possible combinations of i, j, and k. Calculate a and b for each triplet and check if they are equal.
i, j, and k.a and b.a == b, increment count.Intuition
We seek such that . Instead of a nested loop, we can use a hash map to store the indices (or counts and sum of indices) where each prefix XOR has occurred.
Intuition
As shown in the logic representation, is equivalent to . Using prefix XOR array where , the XOR of is . We need . If found, all are valid.
prefix.prefix[i] == prefix[k+1]:
j's is k - i.k - i to total.Detailed Dry Run
arr = [2, 3, 1, 6, 7] Prefix: [0, 2, 1, 0, 6, 1] Pairs with equal prefix values:
Gray Code
An n-bit gray code sequence is a sequence of integers where:
Given an integer n, return any valid n-bit gray code sequence.
Examples
00, 01, 11, 10 is a valid Gray code sequence.
Intuition
Generate the sequence by exploring all possible next numbers that differ by exactly one bit. Maintain a visited set to ensure uniqueness.
Intuition
Gray code for bits can be built from the Gray code for bits by reflecting the sequence and adding a leading 1 (bit ) to the reflected part.
Intuition
The -th number in the Gray code sequence can be generated using the formula . This formula ensures that adjacent numbers differ by exactly one bit because shifting and XORing cancels out bits that change in a ripple carry but leaves the most significant changing bit.
i ^ (i >> 1).Detailed Dry Run
n = 2
Repeated DNA Sequences
Given a string s that represents a DNA sequence, return all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule.
Examples
Intuition
Iterate through every possible 10-letter substring and store it in a hash set. If we encounter a substring that is already in the set, we add it to our result list.
seen hash set to track substrings.repeated hash set to collect result strings.i from 0 to s.length() - 10:
s.substring(i, i + 10).seen, add to repeated.seen.Intuition
Instead of re-extracting substrings, we treat each 10-letter window as a number in base 4 (since there are 4 DNA bases). As we slide the window, we update the hash in time.
Intuition
Since there are only 4 characters, map them to 2 bits. A 10-char sequence is a 20-bit integer. Use a sliding window to update the bitmask in per character.
Maximum Product of Word Lengths
Given a string array words, return the maximum value of length(word[i]) * length(word[j]) where the two words do not share common letters. If no such two words exist, return 0.
Examples
Intuition
Iterate through every pair of words and check if they have common characters using a helper function.
maxProd.Intuition
For each word, precompute a set of its characters. When comparing two words, check if their character sets have any intersection. This is faster than a raw character-by-character check but slower than bitmasking.
Intuition
Each word can be represented by a 26-bit integer (bitmask). Two words share NO common letters if and only if their bitwise AND is 0.
(masks[i] & masks[j]) == 0.Detailed Dry Run
"abcw" -> mask = 0x400007 "xtfn" -> mask = 0x882020 mask1 & mask2 = 0. Product = 4 * 4 = 16.
Maximum XOR of Two Numbers in an Array
Given an integer array nums, return the maximum result of nums[i] XOR nums[j], where .
Examples
Intuition
Check every possible pair of numbers and calculate their XOR sum. Track the maximum value found.
maxResult = 0.nums.maxResult = max(maxResult, nums[i] ^ nums[j]).maxResult.Intuition
We can build the maximum XOR bit by bit. For each bit position (from MSB to LSB), we check if there exists a pair of numbers whose -th bits could potentially form a better maximum XOR than what we have found so far.
Intuition
To maximize XOR, for each number , we want to find another number such that they have different bits at the highest possible positions. A Trie (Prefix Tree) storing binary representations allows us to greedily find the bitwise opposite at each step.
Divide Two Integers
Given two integers dividend and divisor, divide two integers without using multiplication, division, and mod operator.
Examples
10/3 = 3.33333... which is truncated to 3.
7/-3 = -2.33333... which is truncated to -2.
Intuition
Keep subtracting the divisor from the dividend until the dividend becomes smaller than the divisor. The number of times we subtract is the quotient.
INT_MIN).dividend and divisor.dividend >= divisor:
dividend -= divisor.count++.Intuition
The exponential subtraction can be performed recursively. In each call, we find the largest multiple of the divisor that can be subtracted and then recurse on the remainder.
Intuition
Instead of subtracting exactly one divisor at a time, we subtract the largest possible multiple of the divisor using bit shifts (divisor << k). This is equivalent to long division in binary.
dividend >= divisor:
divisor << k <= dividend.dividend -= (divisor << k).quotient += (1 << k).Detailed Dry Run
15 / 3
Total Hamming Distance
The Hamming distance between two integers is the number of positions at which the corresponding bits are different. Return the sum of Hamming distances between all pairs of integers in nums.
Examples
HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.
Intuition
The most direct way is to iterate through every pair in the array, calculate their Hamming distance, and sum them up.
totalDist = 0.Integer.bitCount(nums[i] ^ nums[j]).totalDist.totalDist.Intuition
We can calculate the Hamming distance for each pair by iterating through the numbers and checking each bit. This is similar to the brute force but slightly more structured.
Intuition
Instead of checking pairs, we can check bit positions. For any bit position , if numbers have the -th bit set to 1, and numbers have it set to 0, then there are pairs that differ at this position.
total = 0.total += k * (n - k).total.Detailed Dry Run
nums: [4, 14, 2], n=3 Bit Pos 1: Bits are {0, 1, 0}. k=1, n-k=2. Pairs = 12 = 2. Bit Pos 2: Bits are {1, 1, 0}. k=2, n-k=1. Pairs = 21 = 2. Bit Pos 3: Bits are {0, 1, 0}. k=1, n-k=2. Pairs = 1*2 = 2. Total: 2+2+2 = 6.
Minimum Flips to Make a OR b Equal to c
Given 3 positives a, b and c. Return the minimum flips required in some bits of a and b to make (a OR b == c).
Examples
Intuition
Iterate through each bit of the three numbers and compare the required state c with the current state a | b. Count the flips needed for each bit position.
c is 0:
a and b must be 0. Add their sum to flips.c is 1:
a or b must be 1. If both are 0, add 1 to flips.flips.Intuition
Instead of checking every bit manually, we can use built-in bit counting functions to calculate the flips needed for the entire numbers after identifying which bits are incorrect via XOR and AND.
Intuition
We can use bitwise operators to find all differing bits at once. (a | b) ^ c gives bits that are incorrect. We then handle the cases where c bit is 0 separately as they might require 2 flips per bit.
incorrect = (a | b) ^ c.must_flip_two = a & b & incorrect.incorrect + Count of set bits in must_flip_two.Detailed Dry Run
a=2(0010), b=6(0110), c=5(0101) a|b = 6 (0110) incorrect = 0110 ^ 0101 = 0011 (bits 0 and 1 are wrong) must_flip_two = 0010 & 0110 & 0011 = 0010 (bit 1 is wrong and both a,b are 1) Total = popcount(0011) + popcount(0010) = 2 + 1 = 3.
Sum of All Subset XOR Totals
Return the sum of all XOR totals for every subset of nums.
Examples
Intuition
Generate all possible subsets, calculate the XOR of each, and sum them up.
currentXor value through the recursion tree.currentXor.Intuition
Use a bitmask from 0 to to represent every possible subset of nums. For each mask, calculate the XOR total and add it to the sum.
Intuition
For a bit position , if at least one number in nums has the -th bit set, then in exactly half of the subsets (i.e., ), the XOR total will have the -th bit set. This is because adding a number with the -th bit set flips the -th bit of the XOR sum.
(OR of all nums) * 2^(n-1).Detailed Dry Run
nums = [1, 3], n = 2 OR = 1 | 3 = 3 (binary 11) Sum = 3 * 2^(2-1) = 3 * 2 = 6. Result matches brute force!
Reverse Pairs
Given an integer array nums, return the number of reverse pairs in the array. A reverse pair is a pair such that and .
Examples
Intuition
Check every possible pair where . If the condition is met, increment the counter.
Intuition
Similar to counting inversions, we can use merge sort to count reverse pairs. During the merge step, for each element in the left half, we find how many elements in the right half satisfy .
Intuition
As we iterate through the array, we want to count how many numbers seen so far are greater than . A Binary Indexed Tree (BIT) can efficiently handle point updates and prefix sums. Since values can be large, we use coordinate compression on all and .
nums from right to left (or left to right with adjustments):
Can I Win
Two players take turns choosing integers from 1 to maxChoosableInteger without reuse. The first to reach desiredTotal wins. Return true if the first player can force a win.
Examples
Intuition
Explore all possible sequences of choosing numbers. A player wins if they can pick a number that reaches the total, or if there is a number they can pick such that the other player cannot win from the resulting state.
Intuition
Represent the state of used numbers with a 20-bit integer mask. This is more efficient for passing state through recursion but still suffers from exponential growth without memoization.
Intuition
The state of the game is uniquely determined by which integers have been used. Since maxChoosableInteger is at most 20, we can use a bitmask of length 20 to represent the set of used numbers. Memoizing the results of these masks drastically reduces the number of computations.
mask where the -th bit is 1 if number is used.canWin(mask) in a hash map or array.desiredTotal <= 0 or sum check.Maximum AND Sum of Array
Place n integers into numSlots slots (max 2 per slot). The AND sum is the sum of (nums[i] & slotNumber). Return the maximum possible AND sum.
Examples
Intuition
Try all possible placements of the integers into the slots. Each slot can take up to 2 integers. This is an exhaustive search of the solution space.
Intuition
Identify that the problem has overlapping subproblems. Even without a full ternary mask, we can use a simpler memoization based on the current counts array (converted to a string or tuple) to avoid redundant work.
Intuition
Since each slot can hold up to 2 integers, we can represent the state of the slots using a base-3 integer. In this integer, the -th digit (in base 3) represents the number of elements in slot (0, 1, or 2).
solve(index, mask) where index is the current number in nums we are placing.mask is a base-3 representation of slot occupancies.nums[index] in slot , update mask, and take the results.Help us improve! Report bugs or suggest new features on our Telegram group.