zoukankan      html  css  js  c++  java
  • 231. 2 的幂

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

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

    第一个技巧是

    [ exttt{n & (n - 1)} ]

    其中 ( exttt{&}) 表示按位与运算。该位运算技巧可以直接将 (n) 二进制表示的最低位 (1) 移除,它的原理如下:

    假设 (n) 的二进制表示为 ((a 10cdots 0)_2) ,其中 (a) 表示若干个高位,1 表示最低位的那个 1,(0cdots 0) 表示后面的若干个 (0),那么 (n-1) 的二进制表示为:

    [(a 01cdots1)_2 ]

    我们将 ((a 10cdots 0)_2)((a 01cdots1)_2) 进行按位与运算,高位 (a) 不变,在这之后的所有位都会变为 0,这样我们就将最低位的那个 1 移除了。

    因此,如果 (n) 是正整数并且 ( exttt{n & (n - 1) = 0}),那么 (n) 就是 2 的幂。

    第二个技巧是( exttt{n & (-n)}) 其中 (-n)(n) 的相反数,是一个负数。该位运算技巧可以直接获取 (n) 二进制表示的最低位的 1。

    由于负数是按照补码规则在计算机中存储的,(-n) 的二进制表示为 (n) 的二进制表示的每一位取反再加上 1,因此它的原理如下:

    假设 (n) 的二进制表示为 ((a 10cdots 0)_2) ,其中 (a) 表示若干个高位,1 表示最低位的那个 1,(0cdots 0) 表示后面的若干个 0,那么 (-n) 的二进制表示为:

    [(ar{a} 01cdots1)_2 + (1)_2 = (ar{a} 10cdots0)_2 ]

    其中 (ar{a}) 表示将 (a) 每一位取反。我们将 ((a 10cdots 0)_2)((ar{a} 10cdots0)_2) 进行按位与运算,高位全部变为 0,最低位的 1 以及之后的所有 0 不变,这样我们就获取了 (n) 二进制表示的最低位的 1。

    因此,如果 (n) 是正整数并且 ( exttt{n & (-n) = n}),那么 (n) 就是 2 的幂。

    注意点

    在一些语言中,位运算的优先级较低,需要注意运算顺序。

    class Solution {
    public:
        bool isPowerOfTwo(int n) {
            return n > 0 && (n & (n - 1)) == 0;
        }
    };
    
    class Solution {
    public:
        bool isPowerOfTwo(int n) {
            return n > 0 && (n & -n) == n;
        }
    };
    
  • 相关阅读:
    容器 list
    迭代器
    排序
    extern "C"
    FZU2127
    HDU1102--最小生成树
    HDU1102(最小生成树Kruskal)
    并查集详解(转自一个很有才的大神)膜拜
    C# switch
    Dijkstra(歪果仁的名字真是长。。。)
  • 原文地址:https://www.cnblogs.com/fxh0707/p/15021281.html
Copyright © 2011-2022 走看看