描述 Description

Given an integer, write a function to determine if it is a power of two.

Example

For n=4, return true;

For n=5, return false;

Challenge

O(1) time

[Power of Two]

分析 Analysis

方法1(推荐)

最快速的方法 Time complexity = O(1)

  (number & number - 1) == 0

将2的幂次方写成二进制形式后,很容易就会发现有一个特点:二进制中只有一个1,并且1后面跟了n个0; 因此问题可以转化为判断1后面是否跟了n个0就可以了。

如果将这个数减去1后会发现,仅有的那个1会变为0,而原来的那n个0会变为1;因此将原来的数与去减去1后的数字进行与运算后会发现为零。

  原因:因为2的N次方换算是二进制为10……0这样的形式\(0除外\)。与上自己-1的位数,这们得到结果为0。例如。8的二进制为1000;8-1=7,7的二进制为111。两者相与的结果为0。计算如下:

     1000  
   & 0111  
   -------  
     0000

方法2

同样快速但不是最好的方法 Time complexity = O(1)

2^k次方一定能被最大的2^32整除。毕竟除法最慢了。

Because the range of an integer = -2147483648 (-2^31) ~ 2147483647 (2^31-1), the max possible power of two = 2^30 = 1073741824.

(1) If n is the power of two, let n = 2^k, where k is an integer. We have 2^30 = (2^k) * 2^(30-k), which means (2^30 % 2^k) == 0.

(2) If n is not the power of two, let n = j*(2^k), where k is an integer and j is an odd number. We have (2^30 % j*(2^k)) == (2^(30-k) % j) != 0.

return n>0 && (1073741824 % n == 0);

方法3

使用bitcount计算有多少个1,只有一个1说明是2的幂次方。即一位一位地数。

Note: 一位一位地数就可以知道具体是多少次方了。

如果是2的幂,则二进制的所有位中,有且仅有一个1。

通用方法

方法1:最直接的方法就是不停地除以M,看最后的余数是否为1;O(logMn)?

while(n%M==0) n /= M;

方法2:M^k次方一定能被最大的M^maxk (<2^32)整除。O(1)。

maxPowerOfM = int(pow(m, (int)(log(0x7fffffff) / log(m)))) [数学计算相关算法 ]

maxPowerOfM% n == 0

方法3:利用对数换底公式logMn = logcn / logcM来做,那么如果n是M的幂数,则logMn一定是整数。O(1)的,但是一般比最优的方法慢一点。

Note:

1 如果logcM不精确的话,可能结果就不是整数了。所以c一般选择10,不能随便选!!!

2 n超出2**32也会出错。

3 lz有个问题没时间弄明白,log10及log2在计算机中是如何计算出来的,为什么log10能AC不会出错而log2会因为精度出错呢???

那么如果n是3的幂数,则log3n一定是整数,我们利用换底公式可以写为log3n = log10n / log103,注意这里一定要用10为底数,不能用自然数或者2为底数,否则当n=243时会出错,原因请看这个帖子。现在问题就变成了判断log10n / log103是否为整数,在c++中判断数字a是否为整数,我们可以用 a - int(a) == 0 来判断。

当然python中可以直接指定底数为M来计算(但是应该也是通过换底公式做的),__import__('math').log(num, M),所以要使用__import__('math').log10(num)/...。

方法4:M很大的话可以枚举 O(logMmaxnum)

for such kind of power questions, if we need to check many times, it might be a good idea to store the desired powers into an array first.

如3的幂次方

public boolean isPowerOfThree(int n) {
    int[] allPowerOfThree = new int[]{1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467};
    return Arrays.binarySearch(allPowerOfThree, n) >= 0;
}

方法5:转换到M进制,看是否只有一个1

The idea is to convert the original number into radix-3 format and check if it is of format 10* where 0* means k zeros with k>=0.

如转换成3进制判断。

public boolean isPowerOfThree(int n) {
    return Integer.toString(n, 3).matches("10*");
}

Note: 不过转换成M进制的过程很可能是辗转相除法得到的,类似方法1,所以lz觉得应该是O(n)的。

[算法:位运算 [草稿]]

代码 Code

方法3

//时间复杂度:O(n) 空间复杂度:O(1)
class Solution {
public:
    bool isPowerOfTwo(int n) {
       if (n < 0) return false;
       bool hasOne = false;
       while (n > 0) {
           if (n & 1) {
               if (hasOne) {
                   return false;
               }
               else {
                   hasOne = true;
               }
           }
           n >>= 1;
       }
       return hasOne;
    }
};

方法1

class Solution {
public:
    bool isPowerOfTwo(int n) {
        return n > 0 && !(n&(n-1));
    }
};

results matching ""

    No results matching ""