**虽然二进制的思维并不符合我们日常的思维习惯,但是由于计算机都是基于二进制的,因此位运算方法,常常能够让我们的算法更加高效简洁。**
题目:
实现一个方法,判断一个正整数是否是2的乘方(比如16是2的4次方,返回True;18不是2的乘方,返回False)。要求性能尽可能高。
解法一:
创建一个中间变量Temp,初始值是1。然后进入一个循环,循环中每次让Temp和目标整数比较,如果相等,则说明目标整数是2的乘方;如果不相等,则让Temp增大一倍,继续循环比较。当Temp大于目标整数时,说明目标整数不是2的乘方。
如果目标整数的大小是N,则此方法的时间复杂度是O(LogN)。
解法二:
因为2的乘方都符合一个规律,即 N&N-1 等于 0,所以直接用这个规律判断即可。该算法时间复杂度是O(1)。
代码:
import java.util.Scanner;
public class T{
public static void main(String[] args){
System.out.println("输入一个正整数,判断这个数是不是2的正整数次方:");
int m=new Scanner(System.in).nextInt();
System.out.println(m+"是不是2的正整数次方 \n ----循环算法:"+t1(m)+" \n ----位运算: "+t2(m));
System.out.println("输出10000以内所有2的整数幂:");
int n=2;
while(n<10000){
if(t1(n)){
System.out.print(n+",");
}
n++;
}
n=2;
System.out.println();
while(n<10000){
if(t2(n)){
System.out.print(n+",");
}
n++;
}
n=2;
System.out.println();
}
//循环算法
public static boolean t1(int n){
int k=2;
while (k<=n){
if(k==n) return true;
//k=k*2;
/*
三种移位运算符
<< : 左移运算符,num << 1,相当于num乘以2
>> : 右移运算符,num >> 1,相当于num除以2
>>> : 无符号右移,忽略符号位,空位都以0补齐
*/
k=k<<1;
}
return false;
}
//位运算
/*
n n-1
2 10 1 1
4 100 3 11
8 1000 7 111
16 10000 15 1111
32 100000 31 11111
64 1000000 63 111111
&表示按位与,即同时为1才为1.
因此,只有是n的次方的时候,n&(n-1)=0.
例如:
100
4&(4-1) → 011 → 0
*/
public static boolean t2(int n){
return (n&(n-1))==0?true:false;
}
}