Problem
Given an integer, determine whether it equals 2^k for some non-negative integer k โ that is, whether it belongs to the sequence 1, 2, 4, 8, 16, โฆ.
- Input: n = 16
- Output: true
- Explanation: 16 = 2^4, so it is a power of two.
Counter-example: n = 6 โ false, because 6 = 2 ร 3 and cannot be written as a pure power of two.
Intuition
Every power of two has exactly one set bit in binary โ 16 looks like 10000, 8 looks like 1000, and so on. The straightforward approach just keeps dividing by 2 until hitting an odd number and checks whether that number is 1. The O(1) insight is the bit trick n & (n - 1): subtracting 1 flips every bit at and below the single set bit, so ANDing with the original always yields zero โ and it yields zero for no other positive integer.
Approach 1 โ Repeated Division
Strip factors of 2 one at a time; if you reach 1 you started with a power of two, and if you hit any other odd number you did not.
- Return false if n โค 0.
- While n is divisible by 2, divide n by 2.
- Return whether n equals 1.
1def isPowerOfTwo(n: int) -> bool:
2 if n <= 0:
3 return False
4 while n % 2 == 0:
5 n //= 2 # strip one factor of 2 per iteration
6 return n == 1Time: O(log n) โ the loop runs at most logโ(n) iterations. Space: O(1) โ no auxiliary storage.
Approach 2 โ Bit Trick: n & (n โ 1)
A power of two has exactly one set bit. Subtracting 1 turns that bit off and turns on every bit below it, so the AND of the original and the decremented value is always zero. This check is a single instruction.
- Guard: return false if n โค 0 (the bit trick alone cannot reject zero โ
0 & -1 == 0). - Return
(n & (n - 1)) == 0.
1def isPowerOfTwo(n: int) -> bool:
2 return n > 0 and (n & (n - 1)) == 0Time: O(1) โ single bitwise operation regardless of n. Space: O(1) โ no auxiliary storage.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Repeated Division | O(log n) | O(1) | Readable fallback; no bit manipulation knowledge required |
| Bit Trick: n & (n โ 1) | O(1) | O(1) | Preferred in practice; instantly recognizable pattern in interviews |
Common Mistakes
- Omitting the
n > 0guard with the bit trick โ0 & (0 - 1)evaluates to 0 in two's complement, so the function incorrectly returns true for n = 0 without the guard. - Using
n >= 0instead ofn > 0in the loop approach โ n = 0 is even, so the while loop would divide 0 by 2 forever (0 // 2 == 0 in every language), producing an infinite loop. - Float division in Python โ writing
n = n / 2instead ofn = n // 2introduces floating-point drift for large inputs and breaks the remainder check. - Confusing
n & 1withn & (n - 1)โn & 1tests only the lowest bit (odd/even check);n & (n - 1)clears the lowest set bit entirely; they solve different problems. - Assuming negative inputs are safe โ powers of two are strictly positive; the explicit
n > 0guard is the correct and complete rejection of non-positive inputs, not a minor edge-case detail.
Related Problems
number-of-1-bitsโ applies the samen & (n - 1)trick in a loop to count all set bitscounting-bitsโ builds on single-number popcount to produce bit counts for every integer 0โnsingle-numberโ XOR bit manipulation to isolate the one unpaired element in an arrayreverse-bitsโ bit-by-bit manipulation across a fixed 32-bit integerbitwise-and-of-numbers-rangeโ range AND exploits the same shared-prefix bit structure that defines powers of two