利用位运算O(1)时间判断一个数是否为2的幂
利用位运算O(1)时间判断一个数是否为2的幂
你问到点子上了!这个位运算技巧可是判断2的幂的经典操作,完美契合你要的O(1)时间复杂度要求,原理完全就是你提到的n和n-1的位关系。
核心逻辑拆解
咱们把你说的两个关键点结合起来看:
- 2的正整数幂的二进制表示只有1位是1,比如2是
10、4是100、8是1000; - 当你对这个数减1时,原来那个唯一的1会变成0,它后面的所有低位都会变成1,比如8-1=7是
0111,4-1=3是0011。
这时候把n和n-1做按位与运算(&),结果会出现两种情况:
- 如果n是2的幂:原数唯一的1位在n-1里是0,后面的低位都是1,两者按位与后每一位都是0,最终结果为
0; - 如果n不是2的幂:二进制至少有两个1,减1只会翻转最右边的1及后面的位,左边还有其他1存在,按位与后这些位会保留1,结果肯定不为
0。
必须注意的边界判断
这里一定要加一个前置条件:n必须是正整数。原因很简单:
- n=0时,0-1=-1(二进制补码全1),
0 & -1结果是0,但0显然不是2的幂; - 负数的二进制是补码形式,不可能符合“只有一个1”的特征,所以直接排除。
代码示例(多语言版)
这个逻辑在所有支持位运算的语言里都通用,举几个常用的实现:
- Java/C++:
public static boolean isPowerOfTwo(int n) { return n > 0 && (n & (n - 1)) == 0; }
- Python:
def is_power_of_two(n): return n > 0 and (n & (n - 1)) == 0
- Go:
func isPowerOfTwo(n int) bool { return n > 0 && (n & (n - 1)) == 0 }
实际测试验证
拿几个数试一下就更直观了:
- 测试n=8:
8 & 7 = 1000 & 0111 = 0000→ 返回True; - 测试n=6(二进制110):
6 & 5 = 110 & 101 = 100(即4)≠0 → 返回False; - 测试n=1:
1 & 0 = 0,且1>0 → 返回True(1是2^0,属于2的幂范畴)。
我平时写代码处理内存对齐、分治算法边界判断的时候经常用这个技巧,纯硬件级别的位运算完全没有循环或浮点运算的开销,速度拉满,比循环除2、用对数判断靠谱多了!




