【Leetcode】342. 4的幂

34 阅读1分钟

leetcode-342.png

位运算

  1. n 必须是 2 的幂(二进制中只有一个 1
    用 (n & (n - 1)) === 0 来判断。
  2. 这个唯一的 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)