4的幂
给定一个整数 (32 位有符号整数),请编写一个函数来判断它是否是 4 的幂次方。
示例 1:
输入: 16
输出:yes
示例 2:
输入: 5
输出: no
进阶:
你能不使用循环或者递归来完成本题吗?
分析:
联想到如何确定一个数是否是2的幂,这里有一个可行的方法:假设这个数为x 则只要判断 x > 0 and x & (x - 1) == 0。
方法一:采用循环的方法:
void check(int n){
if (n==1)
cout<<"no"<<endl;
while(n%4==0){
n/=4;
}
if (n==1){
cout<<"yes"<<endl;
}else
{
cout<<"no"<<endl;
}
}
方法二:暴力破解+预计算
我们知道输入的整数是 32 位整数,所以x<=231 -1 ,最大4的幂次为log4(231 -1)=15,一共有16种可能,我们只需要计算这16个特殊值,即可以判断这个数是否是4的幂。
void checkstore(long long x){
long long arr[17];
arr[0]=1;
for (int i =1; i <=16; i++)
{
arr[i]=arr[i-1]*4;
if (x==arr[i])
{
cout<<"yes"<<endl;
return;
}
}
cout<<"no"<<endl;
}
复杂度分析
- 时间复杂度:O(1)。
- 空间复杂度:O(1)。
方法三:数学运算
如果这个数x是4的幂,则x = 4a , a = log4x ,则a = 1/2 log2x, a 为整数,故log2x必须为偶数。只需要判断log2x是否为偶数,就可以判断这个数是否是4的幂。
void check2(long long x){
double result = log2(x);
if (result-int(result)==0)//判断这个数是否为整数
{
if (int(result)%2==0)
{
cout<<"yes"<<endl;
return;
}
}
cout<<"no"<<endl;
}
复杂度分析
- 时间复杂度:O(1)。
- 空间复杂度:O(1)。
方法四:位操作
算法:
我们首先检查 num 是否为 2 的幂:x > 0 and x & (x - 1) == 0。
对于一个整数而言,如果这个数是 4 的幂次方,那它必定也是 2 的幂次方。
我们先将 2 的幂次方列出来找一下其中哪些数是 4 的幂次方。
十进制 二进制
2 10
4 100 (1 在第 3 位)
8 1000
16 10000(1 在第 5 位)
32 100000
64 1000000(1 在第 7 位)
128 10000000
256 100000000(1 在第 9 位)
512 1000000000
1024 10000000000(1 在第 11 位)
找一下规律: 4 的幂次方的数的二进制表示 1 的位置都是在奇数位。
将这个数与特殊的数做位运算。
这个特殊的数有如下特点:
足够大,但不能超过 32 位,即最大为 1111111111111111111111111111111( 31 个 1)
它的二进制表示中奇数位为 1 ,偶数位为 0
符合这两个条件的二进制数是:
1010101010101010101010101010101
如果用一个 4 的幂次方数和它做与运算,得到的还是 4 的幂次方数。
将这个二进制数转换成 16 进制表示:0x55555555 。
oid check3(int num){
if (num <= 0)
cout<<"no";
//先判断是否是 2 的幂
if ((num & num - 1) != 0)
cout<<"no";
//如果与运算之后是本身则是 4 的幂
if ((num & 0x55555555) == num)
cout<<"yes";
cout<<"no";
}