LeetCode 231:
给你一个数n,判断是否是2的幂次方,如果是,返回true;否则,返回false。
如果存在一个整数x使得n==2x,则认为n是n的幂次方。
思路:一个数 n 是 2 的幂,当且仅当 n 是正整数,并且 n 的二进制表示中仅包含 1 个 1。
因此我们可以考虑使用位运算,将 n 的二进制表示中最低位的那个 1 提取出来,再判断剩余的数值是否为 0 即可。下面介绍两种常见的与「二进制表示中最低位」相关的位运算技巧。
- 第一个技巧是 n & (n - 1)
其中 & 表示按位与运算。该位运算技巧可以直接将 n 二进制表示的最低位 1 移除,它的原理如下:
假设 n 的二进制表示为 (a10⋯0) 2 ,其中 a 表示若干个高位,1 表示最低位的那个 1,0⋯0 表示后面的若干个 0,那么 n−1 的二进制表示为:(a01⋯1) 2,我们将 (a10⋯0) 2 与 (a01⋯1) 2 进行按位与运算,高位 a 不变,在这之后的所有位都会变为 0,这样我们就将最低位的那个 1 移除了。
因此,如果 n 是正整数并且 n & (n - 1) = 0,那么 n 就是 2 的幂。
- 第二个技巧是 n & (-n)
其中 −n 是 n 的相反数,是一个负数。该位运算技巧可以直接获取 n 二进制表示的最低位的 1。由于负数是按照补码规则在计算机中存储的,−n 的二进制表示为 n 的二进制表示的每一位取反再加上 1,因此它的原理如下:
假设 n 的二进制表示为 (a10⋯0) 2,其中 a 表示若干个高位,1 表示最低位的那个 1,0⋯0 表示后面的若干个 0,那么 −n 的二进制表示为:
($\overline{a} 01...1 ) 2 + ( 1 ) 2 = ( 01...1)~2~+(1)~2~=( 01...1) 2 +(1) 2 =(\overline{a}$10…0)2
其中 a ‾ \overline{a} a表示将a每一位取反,我们将(a10…0)2与($\overline{a}$10…0)2进行按位与运算,高位全部变成0,最低位的1以及之后的所有0不变,这样我们就获取了n二进制表示的最低位的1.
因此,如果n是正整数并且n&(-n)=n,那么n就是2的幂。
代码
下面分别给出两种位运算技巧对应的代码。
在一些语言中,位运算的优先级较低,需要注意运算顺序。
-
方法一
//C++ class Solution { public: bool isPowerOfTwo(int n) { return n > 0 && (n & (n - 1)) == 0; } };
//java2 class Solution { public boolean isPowerOfTwo(int n) { return n > 0 && (n & (n - 1)) == 0; } }
## python class Solution: def isPowerOfTwo(self, n: int) -> bool: return n > 0 and (n & (n - 1)) == 0
-
方法二
//C++ class Solution { public: bool isPowerOfTwo(int n) { return n > 0 && (n & -n) == n; } };
//java class Solution { public boolean isPowerOfTwo(int n) { return n > 0 && (n & -n) == n; } }
##python class Solution: def isPowerOfTwo(self, n: int) -> bool: return n > 0 and (n & -n) == n
作者:力扣官方题解
链接:https://leetcode.cn/problems/power-of-two/solutions/796201/2de-mi-by-leetcode-solution-rny3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。