
位运算
解题思路:时间复杂度O(
1
1
1),空间复杂度O(
1
1
1) |
---|
- 我们观察正整数中2的幂的二进制表现形式的规律:
-
2
0
=
1
=
0001
2^0=1=0001
20=1=0001
-
2
1
=
2
=
0010
2^1=2=0010
21=2=0010
-
2
2
=
4
=
0100
2^2=4=0100
22=4=0100
-
2
3
=
8
=
1000
2^3=8=1000
23=8=1000
- 也就是说正数中的2的幂,满足一个很重要的条件,那就是整个二进制串只有一个1
- 而题目明确指出,给出的n是整数。也就是说,我们不需要考虑负次幂的情况,例如
2
−
1
=
0.5
,
2
−
2
=
0.25
等
2^{-1}=0.5,2^{-2}=0.25等
2−1=0.5,2−2=0.25等
- 则我们现在的算法就可以简化为,对n的二进制代码最后一个1操作判断即可
- 去除2进制串中最后一个1后,剩余2进制串结果为0.就说明是2的幂,例如
2
3
=
8
=
1000
2^3=8=1000
23=8=1000,取出最后一个1变为
0000
=
0
0000 = 0
0000=0
这个操作也比较经典,Brian Kernighan算法可以方便的实现去除二进制串种末位1的效果。也就是s = n&(n-1),s为n二进制去除末位1的结果串
- 只取末位1,如果刚好=n,说明是2的幂。例如
2
3
=
8
=
1000
2^3=8=1000
23=8=1000,只取末位1为
1000
=
8
1000 = 8
1000=8.发现相等,锁门n是2的幂。再比如
n
=
十
=
二进制
1010
n = 十 = 二进制1010
n=十=二进制1010,只取末位1为
0010
=
2
0010 = 2
0010=2,发现结果2和n不相等,说明n的二进制串不是只有一个1.因此n = 10不是2的幂
这个操作也是经典,只需要通过n&(-n)就可以只取出末位的1
- 以上用到的位运算操作,不懂的可以参考下面的文章中与运算的说明
另外,很重要的一点是,2的幂不可能为负数。因为一个正数的n次幂依然是正数。
- n的2进制串去除末位1后,剩下的二进制是否为0

class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (n & (n-1)) == 0;
}
}
- 只取末位1,结果和n一样,说明是2的幂

class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (n & -n) == n;
}
}