二进制表示中最低位的位运算技巧

LeetCode 231:

给你一个数n,判断是否是2的幂次方,如果是,返回true;否则,返回false。

如果存在一个整数x使得n==2x,则认为n是n的幂次方。

思路:一个数 n 是 2 的幂,当且仅当 n 是正整数,并且 n 的二进制表示中仅包含 1 个 1。

因此我们可以考虑使用位运算,将 n 的二进制表示中最低位的那个 1 提取出来,再判断剩余的数值是否为 0 即可。下面介绍两种常见的与「二进制表示中最低位」相关的位运算技巧。

  1. 第一个技巧是 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 的幂。

  1. 第二个技巧是 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的幂。

代码

下面分别给出两种位运算技巧对应的代码。
在一些语言中,位运算的优先级较低,需要注意运算顺序

  1. 方法一

    //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
    
  2. 方法二

    //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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值