1、问题描述
2、位运算解法
一个数是2的幂,当且仅当该数为正整数且其二进制表示中仅包含一个1。因此可以将最低位1提取出来后判断剩余位置数值是否为0即可解出该题
1、n & (n - 1) == 0
- 例如:
- 16 & 15 = 10000 & 01111 = 0
- 15 & 14 = 01111 & 01110 != 0
- 代码如下:
class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
}
}
2、n & (-n) == n
- 注意这里的 -n 是 n 的相反数,由于 n 为正整数,因此 -n 一定是一个负数;而负数是通过补码保存在计算机中的,-n 的二进制表示为 n 的二进制表示逐位取反1最后加一
- 例如:
- 16 & (-16) = 10000 & (01111 + 1) = 10000 & 10000 = 10000 = 16
- 15 & (-15) = 01111 & (10000 + 1) != 01111
- 代码如下
class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (n & -n) == n;
}
}
3、异或运算
n ^ (n-1) == ((n << 1) - 1)
- 例如:
- 16 ^ 15 = 10000 ^ 01111 = 11111 = 31 = 32 - 1
- 15 ^ 14 = 01111 ^ 01110 = 00001
class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (n ^ (n -1)) == (n << 1) - 1;
}
}
3、扩展:判断n是否为4的幂次?
要判断一个数是否是4的幂次,首先需要保证这个数是2的幂次,因此可以在上面解法的基础上进行判断,如果满足2的幂次,那么说明该数二进制形式只有一个1
-
接下来如果 n 是 4 的幂,那么 n 的二进制表示中一定有且仅有一个 1,并且这个 1 后面必须有偶数个 0。以最低位为0,也就是说唯一的1出现在偶数位上
-
例如:
- 4 = 100
1出现在第2位上
- 16 = 10000
- 64 = 1000000
- …
- 4 = 100
-
由于题目保证了 n 是一个 32 位的有符号整数,因此可以构造一个整数 mask,它的所有偶数二进制位都是 0,所有奇数二进制位都是 1。
-
这样一来,将 n 和 mask 进行按位与运算,如果结果为 0,说明 n 二进制表示中的 1 出现在偶数的位置,否则说明其出现在奇数的位置。
根据上面的思路,mask 的二进制表示为:
mask = 10101010101010101010101010101010 = 0xaaaaaaaa(十六进制)
例如:- 4 & mask = 0100 & (0xaaaaaaa1010) = 0
- 2 & mask = 0010 & (0xaaaaaaa1010) = 2 != 0
代码如下:
class Solution {
public boolean isPowerOfFour(int n) {
return n > 0 && (n & (n - 1)) == 0 && (n & 0xaaaaaaaa) == 0;
}
}
**补充:**由于题中指出n的范围为整数范围,因此需要考虑到符号,所以就不需要要考虑第一个1010的第一位即符号位了,它与值无关,因此十六进制的0xaaaaaaaa可以转换为0x2aaaaaaaa