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

题目:请实现一个函数,输入一个整数,输出该数二进制表示中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.很多二进制的为题都可以用这个

思路解决

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值