位运算
n必须是 2 的幂(二进制中只有一个1)
用(n & (n - 1)) === 0来判断。- 这个唯一的
1必须在偶数位
用(n & 0xAAAAAAAA) === 0来判断。
-
这里的
0xAAAAAAAA是十六进制数:- 十六进制
A的二进制表示是1010 - 在 32 位整数中,
0xAAAAAAAA的二进制是:
- 十六进制
// 它在奇数位都是 1,偶数位都是 0。
10101010 10101010 10101010 10101010
这样:
- 如果
n唯一的1在偶数位,与0xAAAAAAAA相与的结果一定是0 - 如果
n唯一的1在奇数位,与掩码相与的结果会大于 0
var isPowerOfFour = function (n) {
return n > 0 && (n & (n - 1)) === 0 && (0xaaaaaaaa & n) === 0;
};
为什么不能省略 (n & (n - 1)) === 0?
(n & 0xAAAAAAAA) === 0 只能确保 n 的所有 1 都在偶数位,但不能保证只有一个 1。
对于10100(20)这个数字而言,此时和 0xaaaaaaaa 来进行 & 运算,可以得到
10100(20)
01010(10 -- 0xA)
00000
此时也可以得到 (0xaaaaaaaa & n) = 0,这个结论,但是是错的
因为0xaaaaaaaa只能保证偶数位上都是1,从而来进行检测,但是n里面的奇数位出现多个1的时候,也就是上面的10100(20),此时也会得到 (0xaaaaaaaa & n) = 0,从而进行了错误的判断
所以我们需要保证n里面只有一个1,那就是用 n & (n - 1)) = 0 来进行保证
数学方式
var isPowerOfFour = function (n) {
if (n <= 0) return false;
while (n % 4 === 0) {
n = n / 4;
}
return n === 1;
};
时间复杂度是 O(log₄n)