A clear explanation of Power of Four using bit manipulation and binary properties.
Problem Restatement
We are given an integer n.
Return true if n is a power of four. Otherwise return false.
A number is a power of four if there exists an integer x such that:
n = 4^xExamples:
1 = 4^0
4 = 4^1
16 = 4^2
64 = 4^3are powers of four.
The official problem asks whether n is a power of four and includes a follow-up asking for a solution without loops or recursion. (leetcode.com)
Input and Output
| Item | Meaning |
|---|---|
| Input | Integer n |
| Output | true if n is a power of four |
| Valid form | n = 4^x for some integer x >= 0 |
Function shape:
def isPowerOfFour(n: int) -> bool:
...Examples
Example 1:
Input: n = 16
Output: trueBecause:
16 = 4^2Example 2:
Input: n = 5
Output: falseThere is no integer x such that:
4^x = 5Example 3:
Input: n = 1
Output: trueBecause:
1 = 4^0First Thought: Repeated Division
A direct approach is:
- While
nis divisible by4:- Divide
nby4.
- Divide
- At the end, check whether
n == 1.
class Solution:
def isPowerOfFour(self, n: int) -> bool:
if n <= 0:
return False
while n % 4 == 0:
n //= 4
return n == 1This works, but the follow-up asks for a constant-time bit solution.
Key Insight
A power of four is also a power of two.
So first check whether n has exactly one set bit.
For powers of two:
n & (n - 1) == 0Examples:
| Number | Binary |
|---|---|
1 | 0001 |
2 | 0010 |
4 | 0100 |
8 | 1000 |
Subtracting 1 flips all bits after the single set bit.
Example:
8 = 1000
8 - 1 = 0111
AND = 0000But powers of two are not enough.
For example:
8 = 2^3is not a power of four.
So we need another property.
Binary Pattern of Powers of Four
Powers of four have their single 1 bit at even bit positions.
Examples:
| Number | Binary | Set bit position |
|---|---|---|
1 | 0001 | 0 |
4 | 0100 | 2 |
16 | 00010000 | 4 |
64 | 01000000 | 6 |
All are even positions.
The hexadecimal mask:
0x55555555has binary form:
01010101010101010101010101010101It keeps only even-position bits.
So a number is a power of four if:
n > 0nis a power of two- Its set bit is in an even position
The third condition is:
n & 0x55555555 != 0Algorithm
Return whether all three conditions hold:
n > 0
and n & (n - 1) == 0
and n & 0x55555555 != 0Walkthrough
Use:
n = 16Binary:
16 = 00010000Check positivity:
16 > 0true.
Check power of two:
16 & 15
00010000
00001111
--------
00000000So 16 has exactly one set bit.
Check even-position mask:
16 & 0x55555555 != 0The set bit survives because it is at position 4, which is even.
Return True.
Now use:
n = 8Binary:
8 = 00001000It passes the power-of-two check.
But its set bit is at position 3, which is odd.
So:
8 & 0x55555555 == 0Return False.
Correctness
If the algorithm returns true, then:
n > 0n & (n - 1) == 0n & 0x55555555 != 0
The second condition means n has exactly one set bit, so n is a power of two.
The third condition means that set bit is located at an even bit position.
Powers of four are exactly the powers of two whose single set bit appears at positions:
0, 2, 4, 6, ...Therefore n must equal:
4^xfor some nonnegative integer x.
Now suppose n is a power of four.
Then n is positive.
Its binary representation contains exactly one set bit, so:
n & (n - 1) == 0Also, powers of four place that bit at an even position, so:
n & 0x55555555 != 0Therefore all three conditions hold, and the algorithm returns true.
So the algorithm returns true exactly for powers of four.
Complexity
| Metric | Value | Why |
|---|---|---|
| Time | O(1) | Constant number of bit operations |
| Space | O(1) | No extra data structures |
Implementation
class Solution:
def isPowerOfFour(self, n: int) -> bool:
return (
n > 0
and (n & (n - 1)) == 0
and (n & 0x55555555) != 0
)Code Explanation
First check positivity:
n > 0Negative numbers and zero cannot be powers of four.
Then check whether n is a power of two:
(n & (n - 1)) == 0This ensures there is exactly one set bit.
Finally check whether that bit is in an even position:
(n & 0x55555555) != 0The mask keeps only bits at positions:
0, 2, 4, 6, ...If all conditions are true, n is a power of four.
Testing
def run_tests():
s = Solution()
assert s.isPowerOfFour(1) == True
assert s.isPowerOfFour(4) == True
assert s.isPowerOfFour(16) == True
assert s.isPowerOfFour(64) == True
assert s.isPowerOfFour(2) == False
assert s.isPowerOfFour(8) == False
assert s.isPowerOfFour(5) == False
assert s.isPowerOfFour(0) == False
assert s.isPowerOfFour(-4) == False
print("all tests passed")
run_tests()Test meaning:
| Test | Why |
|---|---|
1 | Smallest power of four |
4, 16, 64 | Standard powers of four |
2, 8 | Powers of two but not four |
5 | Random non-power |
0 | Zero case |
-4 | Negative number |