您的位置:首页 > 其它

位运算:二进制中1的个数

2016-03-05 16:32 369 查看
题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。因此输出2.

1.可能引起死循环的解法:

一个基本思路:先判断整数二进制表示中最右边一位是不是1。接着把输入的整数右移一位,此时原来处于从右边数起的第二位被移到最右边了,再判断是不是1。这样每次移动1位,直到整个整数变成0为止。判断最右边是不是1,只要把整数和1做位与运算看结果是不是0就直到了。1除了最右边一位之外所有位都是0.如果一个整数与1做与运算的结果是1,表示该整数最右边一位是1,否则是0. 代码如下:

public static int numberOfOne1(int num){
int count = 0;
int rs=0;
while(num!=0){
if((rs =num & 1)!=0)
count++;
num = num >> 1;
}
return count;
}


但是当输入一个负数时,移位后,最高位仍然为1,如果一直做右移运算,这个数字会变成0xffffffff, 进入死循环。

2.常规解法

为了避免死循环,我们可以不右移输入的数字n. 首先把n和1做与运算,判断n的最低位是不是1.接着把1左移一位得到2,再和n做与运算,判断n的次低位是不是1…这样反复左移,每次都能判断n的其中一位是不是1.基于这种思路,代码如下:

public static int numberOfOne2(int num){
int count1 = 0;
int flag = 1;
int rs = 0;
int count2 = 0;
while(count2<Integer.SIZE){
if((rs=num&flag)!=0)
count1++;
flag = flag << 1;
count2++;
}
return count1;
}


循环次数等于整数二进制的位数。

3.惊喜解法

思路: 如果把一个整数减去1,再和 原整数做与运算,会把该整数最右边一个1变成0.如二进制1100,减去1后变为1011,1100和1011做位与运算是1000.把1100最右边的1变成了0

那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。代码如下:

public static int numberOfOne3(int num){
int count = 0;
while(num!=0){
num = (num-1) & num;
count++;
}
return count;
}


判断一个整数是不是2的整数次方。一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,
而其他所有位是0.把这个整数减去1之后再和它自己做与运算,这个整数中唯一的1就会变成0.

public static boolean is2pow(int num){
return (num & (num-1))==0;
}

输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n.比如10的二进制表示为1010,13的
二进制表示为1101,需要改变1010中的3位才能得到1101. 分两步解决:第一步求这两个数的异或,第二步统计
异或结果中1的个数

public static int diff(int num1, int num2){
int num = num1 ^ num2;
int count = numberOfOne3(num);
return count;
}

把一个整数减去1之后再和原来的整数做位与运算,得到的结果相当于是把整数的二进制表示中的最右边一个1变成0.很多二进制的为题都可以用这个


思路解决
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: