๐ค Why Power Detection Matters: The Binary Signature
Imagine you're designing a hash table. Most hash tables use a power-of-two size because it lets you replace the expensive modulo operation with a lightning-fast bitmask: hash & (size - 1). But how do you know if a number is a power of two?
This is a fundamental pattern โ power detection appears in memory allocators, image processing, error-correcting codes, and countless coding interviews at FAANG companies. And here's the interesting part: different bases need completely different detection strategies.
Let's understand each approach, from the classic bit trick for powers of two to mathematical detection for bases like 3 that have no simple binary pattern.
Tip
๐ก The Key Insight: Powers of two have a clean binary signature โ exactly one bit set. Powers of four are a subset (the lone bit at an even position). Powers of three? No binary pattern โ we use math. Each base needs a different tool!
1. Is Power of Two โ The Classic Bit Trick
Problem: Given an integer n, determine if it is a power of two. A number is a power of two if there exists an integer k such that n = 2แต.
Note
๐ฆ Real-World Analogy: Imagine you're a bank teller counting money. A power of two is like having a single $100 bill โ it can't be broken into smaller bills of the same denomination. In binary, each place value is a power of two: 1, 2, 4, 8, 16... A number that has exactly ONE of these place values turned on โ that's a power of two. Like having exactly one coin in your pocket, and it's a $2^k denomination.
๐ค Think About It
What does a power of two look like in binary? Let's check:
Spot the pattern? Every power of two has EXACTLY ONEbit set to 1. That's the signature! So the problem reduces to: "Does this number have exactly one set bit?"
Brute Force Approach
function isPowerOfTwoBrute(n) {
if (n <= 0) return false;
while (n % 2 === 0) n /= 2;
return n === 1;
}
// n=16 โ 8 โ 4 โ 2 โ 1 โ true (3 iterations)
// n=6 โ 3 โ not divisible by 2 โ false
โ This works. But O(log n) time. We can do BETTER โ O(1) with a bit trick!
๐ Real-Time Thinking โ What Do I Know?
"I need to check if a number is a power of two. Brute force: repeatedly divide by 2. That's O(log n). But powers of two have a special binary property: exactly one bit is set. So 16 = 10000, 8 = 1000, 4 = 100, 2 = 10, 1 = 1. Now, I know that n & (n-1) clears the lowest set bit. If the number only has ONE set bit, clearing it gives 0. So the check becomes: n > 0 && (n & (n-1)) === 0. Let me verify: 16 & 15 = 10000 & 01111 = 0. Yes! 12 & 11 = 01100 & 01011 = 01000 = 8, not 0. So 12 isn't a power of two. The trick works!"
โจ The Magic: n & (n-1)
Here's where the bit manipulation MAGIC happens. There's a property: subtracting 1 from a number flips the lowest set bit to 0 and all bits to the right to 1. Then ANDing the original with this result clears the lowest set bit.
If only one bit was set, the result is 0 โ power of two!
๐ Edge Cases to Consider
n = 0: 0 & (0-1) = 0 & -1 = 0, but 0 is NOT a power of two. The n > 0 check catches this.
n = 1: 1 = 2โฐ, which IS a power of two. 1 & 0 = 0 โ returns true (after n > 0 check).
n = -8 (negative power of two): -8 in two's complement has many bits set. The n > 0 check returns false.
n = 2^31 (beyond 32-bit signed max): JavaScript bitwise ops only work on 32-bit signed. 2^31 = -2147483648 (overflows). Use BigInt for larger values.
n = Number.MAX_SAFE_INTEGER: Bitwise ops truncate to 32 bits. Not a reliable check for numbers > 2^31-1.
๐ Why n & (-n) works: In two's complement, -n = ~n + 1. The AND of n and -n isolates the rightmost 1-bit. For powers of two, there's only ONE set bit, so the result equals n itself. This trick is also used in Fenwick Trees (Binary Indexed Trees)!
Edge Cases
n โค 0? False โ the n > 0 check catches negatives and zero
n = 1? True โ 1 = 2โฐ, it IS a power of two (single bit at position 0)
Very large numbers? JavaScript bitwise ops work on 32-bit signed integers โ use BigInt for larger values
Tip
โก Interview Tip: The moment you hear "power of two" in an interview, your brain should go INSTANTLY to n > 0 && (n & (n-1)) === 0. Say it out loud: "A power of two has exactly one set bit. n & (n-1) clears the lowest set bit. If the result is zero, it's a power of two." This is THE most well-known bit manipulation trick โ know it cold.
PROBLEMPower of Two
Given an integer n, return true if it is a power of two. Use the bitwise approach: n > 0 && (n & (n-1)) == 0.
Loading playground...
2. Is Power of Four โ The Mask Technique
Problem: Given an integer n, determine if it is a power of four.
Here's the interesting twist: every power of four is ALSO a power of two (because 4แต = 2ยฒแต). But the reverse is NOT true โ 2 and 8 are powers of two but NOT powers of four. So how do we distinguish them?
Note
๐ฏ Real-World Analogy: Think of powers of four as a subset of powers of two โ like how every square number is a specific kind of number. If powers of two are seats in a theater, powers of four are only the EVEN-numbered seats (seat 0, 2, 4, 6...). You first check if there's exactly one person in the theater (power of two), then check if they're sitting in an even-numbered seat (the 0x55555555 mask).
๐ค Binary Pattern of Powers of Four
Let's look at the binary patterns:
4^0 = 1 โ 0001 (bit at position 0 โ EVEN)
4^1 = 4 โ 0100 (bit at position 2 โ EVEN)
4^2 = 16 โ 10000 (bit at position 4 โ EVEN)
4^3 = 64 โ 1000000 (bit at position 6 โ EVEN)
Compare with powers of two that are NOT powers of four:
2^1 = 2 โ 0010 (bit at position 1 โ ODD) โ
2^3 = 8 โ 1000 (bit at position 3 โ ODD) โ
Pattern spotted! Powers of four have their lone set bit at an EVEN position (0-indexed from LSB). Powers of two that aren't powers of four have their bit at an ODD position.
โจ The Mask: 0x55555555
0x55555555 is a mask with bits set at ALL even positions. In binary: 0101 0101 0101 0101 0101 0101 0101 0101.
If n is a power of two AND (n & 0x55555555) !== 0, then the lone bit is at an even position โ power of four!
function isPowerOfFour(n) {
return n > 0
&& (n & (n - 1)) === 0 // Must be power of two first
&& (n & 0x55555555) !== 0; // Lone bit at even position?
}
// n=4 (100) โ power of two โ, 100 & 0x55555555 = 100 โ True โ
// n=16 (10000) โ power of two โ, 10000 & 0x55555555 = 10000 โ True โ
// n=2 (10) โ power of two โ, 10 & 0x55555555 = 0 โ False โ
// n=8 (1000) โ power of two โ, 1000 & 0x55555555 = 0 โ False โ
Alternative: (n-1) % 3 === 0
There's also a mathematical property: if n is a power of four, then (n - 1) % 3 === 0. This works because 4แต = (3+1)แต, and expanding the binomial gives terms all divisible by 3 except the last +1.
โ ๏ธ Precision Warning: Don't use Math.log(n) / Math.log(4)for power-of-four detection. Floating-point precision can give false results for large numbers (e.g., Math.log(536870912) / Math.log(4)may not be exactly an integer).
Note
๐ Summary: Power of four = Power of two + even-position mask. The 0x55555555 mask is the standard approach in interviews. The (n-1) % 3 trick is a nice bonus to know!
PROBLEMPower of Four
Given an integer n, return true if it is a power of four. Check power of two first, then verify the lone bit is at an even position using 0x55555555.
Loading playground...
3. Is Power of Three โ Mathematical Detection
Problem: Given an integer n, determine if it is a power of three.
Now this is where things get INTERESTING. Three is NOT a power of two, so there's no simple bit pattern to check. The binary representation of powers of three (1, 3, 9, 27, 81...) doesn't follow a clean positional pattern. We need to get mathematical.
See? No consistent bit pattern. We can't use the n & (n-1) trick here. Let's look at the mathematical approaches.
โจ The Magic: 3^19 % n === 0
The largest power of three that fits in a 32-bit signed integer is 3ยนโน = 1,162,261,467. If n is a power of three, then this maximum power MUST be divisible by n:
function isPowerOfThree(n) {
// 3^19 = 1162261467 is the max power of three in 32-bit signed int
return n > 0 && 1162261467 % n === 0;
}
// n=27: 1162261467 % 27 = 0 โ True (3^3)
// n=9: 1162261467 % 9 = 0 โ True (3^2)
// n=6: 1162261467 % 6 = 3 โ False (not power of three)
// n=12: 1162261467 % 12 = 3 โ False (not power of three)
๐ Why 3^19?
In a 32-bit signed integer system (Java's int), the maximum value is 2,147,483,647. The largest power of three below this is 3ยนโน = 1,162,261,467. Every power of three divides this number because:
// If n = 3^k, then:
// 3^19 / n = 3^19 / 3^k = 3^(19-k) โ integer
// โ No remainder โ 3^19 % n == 0
// If n is NOT a power of three, the modulo is non-zero.
// The only divisors of 3^19 are powers of three!
Alternative: Iterative Division
function isPowerOfThree(n) {
if (n <= 0) return false;
while (n % 3 === 0) n /= 3;
return n === 1;
}
// Time: O(log_3 n) โ about 20 iterations max for 32-bit
// Space: O(1)
This is O(log n) vs the O(1) mathematical approach, but it works universally without needing to precompute the maximum power.
Key Insight
๐ Key Insight: The 3^19 % n trick is O(1) but only works for 32-bit integers. For 64-bit, use 3โดโฐ = 12,157,665,459,056,928,801. For Python's arbitrary-precision integers, pick the right maximum. The iterative approach is slower but works for ANY size.
Warning
โ ๏ธ Interview Note: If the interviewer asks "What about powers of five? Powers of seven?" โ the mathematical approach generalizes! Find the largest power of that base in the integer range, then check divisibility. But the iterative division approach always works.
PROBLEMPower of Three
Given an integer n, return true if it is a power of three. Use the mathematical approach: 3^19 = 1162261467 % n == 0.
Loading playground...
4. Integer Replacement โ The Greedy Strategy
Problem: Given a positive integer n, you can apply these operations:
If n is even: replace n with n/2
If n is odd: replace n with either n+1 or n-1
Return the minimum number of operations to reduce n to 1. This is LeetCode 397, and it's a fascinating problem because the decision for odd numbers isn't obvious!
๐ค The Decision: Add or Subtract?
When n is odd, I face a choice: "Do I choose n+1 or n-1?" Both lead to an even number in the next step. This is the classic choose/not-choose dilemma. If I choose n-1, the next step gives (n-1)/2. If I choose n+1, the next step gives (n+1)/2. Which path leads to more consecutive divisions by 2? The answer depends on the binary pattern. If n ends with ...01, n-1 ends with ...00 (two trailing zeros). If n ends with ...11, n+1 ends with ...000 (at least three trailing zeros). More trailing zeros = more free divisions = fewer total steps!
๐ค The Dilemma
If n is even, the choice is obvious โ divide by 2. That's always optimal.
But if n is odd? Both n+1 and n-1 are even, so both lead to a division by 2 in the next step. Which one leads to MORE consecutive divisions? That's the key to minimizing steps!
๐ Edge Cases to Consider
n = 1: Already at target. 0 steps. The while loop doesn't execute.
n = 2: 2 โ 1. One division. 1 step.
n = 3: Special case! 3 โ 2 โ 1 (2 steps) is better than 3 โ 4 โ 2 โ 1 (3 steps). The rule says subtract, not add.
n = Integer.MAX_VALUE (large odd): Adding 1 could overflow. In JavaScript, use >>> 0 or handle with BigInt.
n is very large (near 2^31): n+1 might overflow to a negative number in 32-bit signed. The division still works but may produce unexpected results.
When n is odd, both n+1 and n-1 are even. The next step will be a division by 2. But the number we get after division determines how many MORE consecutive divisions we can perform:
n % 4
Binary Pattern
Choose
Why
1
...01
n - 1
n-1 ends in 00 โ two divisions: (n-1)/2 is even
3
...11
n + 1
n+1 ends in 00 โ at least two divisions: (n+1)/2 is even
n == 3
11
n - 1
Special case: 3โ2โ1 (2 steps) beats 3โ4โ2โ1 (3 steps)
Key Insight
๐ The Core Intuition: We want to maximize trailing zeros after each operation because trailing zeros mean free divisions by 2. Binary ...01 โ subtract gives ...00 (two trailing zeros). Binary ...11 โ add gives ...000 (three trailing zeros). The n=3 exception is because both paths converge at 2.
PROBLEMInteger Replacement
Given a positive integer n, replace it with n/2 if even, or n+1/n-1 if odd. Return the minimum steps to reduce n to 1. Use greedy strategy based on n mod 4.
Loading playground...
5. Binary String Reduction โ Steps to Zero
Problem: Given a non-negative integer num, count the steps to reduce it to zero. In each step:
If the current number is even: divide by 2
If the current number is odd: subtract 1
This is LeetCode 1342, and it has a BEAUTIFUL closed-form solution once you understand the binary pattern.
๐ Real-Time Thinking โ What Do I Know?
"If n is even, divide by 2. If n is odd, subtract 1. Let me think about this in binary... Every time I divide by 2, I right-shift the binary representation by 1. Every time I subtract 1 from an odd number, I clear the LSB (turn the trailing 1 into 0). So each bit (except the MSB) needs one divide-by-2 operation. Each 1-bit needs one subtract-1 operation. That means total steps = (number of bits - 1) + (number of 1-bits). Let me verify with n=14 (1110): bits=4, ones=3. Steps = 4-1+3 = 6. That matches the step-by-step walkthrough!"
๐ค The Binary Insight
Let's read the binary representation from LEFT to RIGHT (MSB to LSB):
Every 1 bit needs: subtract 1 (to clear it) + divide by 2 (shift right)
Every 0 bit needs: divide by 2 only
The MSB (leftmost 1) only needs one subtract โ no divide after the last bit
Formula:steps = (number of bits) - 1 + (number of 1 bits)
๐ Why the Formula Works: Each bit position (except the MSB) requires a divide by 2 operation โ that's len(binary) - 1divisions. Each 1 bit requires a subtract-1 operation โ that's countOfOnes subtractions. Total = divisions + subtractions. The MSB's subtract is already counted in countOfOnes, and its "divide" doesn't exist because there's nothing to the left.
Edge Cases
n = 0: Already zero, 0 steps. Formula: "0" has len=1, ones=0 โ 1-1+0 = 0 โ
n = 1 (power of two): Binary "1", len=1, ones=1 โ 1-1+1 = 1 step (just subtract 1)
n = 2 (power of two): Binary "10", len=2, ones=1 โ 2-1+1 = 2 steps (รท2, -1)
n = 2แต (any power of two): Binary "1" + k zeros, ones=1, len=k+1 โ steps = k+1-1+1 = k+1
PROBLEMNumber of Steps to Reduce a Number to Zero
Given an integer num, return the number of steps to reduce it to zero. If even, divide by 2; if odd, subtract 1. Use the formula: steps = len(binary) - 1 + count('1').
Loading playground...
6. Gray Code โ The Single-Bit Flip Sequence
Problem: An n-bit Gray code sequence is a sequence of 2โฟ integers where every two consecutive integers differ by exactly one bit. Given n, return any valid n-bit Gray code sequence.
Gray code was invented by Frank Gray at Bell Labs in 1953 for pulse code communication. It's used in error correction, Karnaugh maps, rotary encoders, and ADC/DAC converters. And the formula is SURPRISINGLY simple.
Note
๐ฐ Real-World Analogy: Imagine a combination lock where each digit is a binary digit. Normal binary counting is like turning multiple dials at once (like a car odometer going from 0111 to 1000 โ all four digits change). Gray code is like having a lock where you only turn ONE dial at a time. It's easier to read reliably because you never have a moment where multiple digits are changing simultaneously. The formula G(i) = i ^ (i >> 1) generates this sequence magically.
โจ The Magic Formula: G(i) = i ^ (i >> 1)
That's it. ONE XOR operation. For i from 0 to 2โฟ-1, compute:
โก Pro Tip: The Gray Code sequence length is ALWAYS a power of two (2โฟ). The sequence wraps around cyclically โ the last value differs from the first by exactly one bit. This is why Gray code is so useful in rotary encoders: even if the encoder is in a "transitional" position, you never get garbage readings.
PROBLEMGray Code
An n-bit Gray code sequence is a sequence of 2^n integers where consecutive integers differ by exactly one bit. Generate the sequence using: gray = i ^ (i >> 1).
Loading playground...
๐ฏ Interview Cheat Sheet
Key Insight
Q1: What's the O(1) trick to check power of two? n > 0 && (n & (n-1)) === 0. The AND clears the lowest set bit. If the result is 0, there was only one set bit โ that's a power of two.
Key Insight
Q2: How does power of four differ from power of two? Every power of four is a power of two, but the reverse isn't true. Add the check (n & 0x55555555) !== 0 to ensure the lone bit is at an even position. Or use (n-1) % 3 === 0.
Key Insight
Q3: Why can't we use bit tricks for power of three? Because 3 is not a power of two. Powers of three have no consistent binary pattern. Use the mathematical approach: largest power of three in 32-bit รท n has no remainder. Or use iterative division.
Key Insight
Q4: What's the greedy rule for Integer Replacement? Even โ divide. Odd and n%4==1 (or n==3) โ subtract. Odd and n%4==3 โ add. This maximizes trailing zeros after the next operation, giving more free divisions.
Key Insight
Q5: What's the formula for steps to reduce a number to zero? steps = len(binary) - 1 + count_of_1_bits. Each bit (except MSB) needs a divide. Each 1-bit needs a subtract. That's the whole formula.
Key Insight
Q6: How do you generate Gray Code? G(i) = i ^ (i >> 1) for i from 0 to 2โฟ-1. Each consecutive pair differs by exactly one bit. To convert back: XOR with all right-shifted versions of the Gray code.
Key Insight
Q7: How does n & (-n) isolate the lowest set bit? In two's complement, -n = ~n + 1. When you AND n with -n, only the lowest set bit survives. For a power of two, n & (-n) === n.
๐ Key Takeaways
Power of two โ n > 0 && (n & (n-1)) === 0. Exactly one set bit = power of two. This is THE most important bit trick.
Power of four โ Power of two + even-position mask (n & 0x55555555). The lone bit must be at an even position.
Power of three โ Cannot use bit tricks. Use math:3^19 % n === 0 (32-bit) or iterative division.
Integer Replacement โ Greedy strategy: even โ รท2, oddโn%4==1 โ -1, oddโn%4==3 โ +1. Maximize trailing zeros for free divisions.
Binary String Reduction โ Formula:steps = len(binary) - 1 + count('1'). Every bit tells you what to do.
Gray Code โ G(i) = i ^ (i >> 1). Generates a sequence where consecutive values differ by exactly one bit.
Different bases need different approaches โ Power-of-two bases (2, 4, 8, 16) use bit ops. Non-power-of-two bases (3, 5, 7) use math.
Time: O(1), Space: O(1) โ Bit manipulation solutions are always constant time and space. Mathematical approaches are also O(1) for fixed-width integers.
Understand WHY โ Don't just memorize formulas. Understand the binary patterns: why n&(n-1) clears the lowest set bit, why trailing zeros mean free divisions, why XOR with shift produces Gray code.
Practice! โ The only way this becomes second nature is by solving problems. The Playground is your dojo ๐ฅ
Note
๐ฎ What's Next? Now that you've mastered power detection, head over to Bit Masking & Complementsto learn about complement, binary gap, base conversion, and more!