二进制中“1”的个数

二进制中“1”的个数


问题是这样的, 对于一个字节(8bit)的无符号整型变量,求其二进制表示中“1”的个数

除2余1

一个8位整型,除了末位,其他均是2的整次幂。如果模2后余1,那么必然末位是1,个数+1,否则末位为0。然后**/2**,进行一次降幂,高位就会落至低一位,去检查下一位,直到整个数为0。

	public int count1(int n) {
        int num = 0;
        while (n > 0) {
            if (n % 2 == 1)//模1相加
                num++;
            n /= 2;

        }
        return num;
    }

与1位运算

同样是每次去看末位是否为1。将整数与00000001进行与操作(&),因为前7位为0,所以结果的前7为必为0;末位若为1,则结果末位为1,整个得数为1,num+1,末位为0则答案为0,num+0。此时末位检测完毕无用,右移一位,重复上述过程,直到为0。

	public int count2(int n) {
        int num = 0;
        while (n > 0) {
            num += (n&1);//讲位运算的结果加上 1 or 0
            n = n >> 1;
        }
        return num;
    }

高效位操作

我们发现,前面两种操作,对于一些数,比如10000000,就会浪费大量时间在无用的0上,那么能不能让算法的复杂度只与“1”的个数有关呢?
n与n-1进行与操作&,可以瞬间判断从末位开始到最近的“1”,这么多位,然后将结果赋值给n。这样就不用一个一个判断末位了。

每进行一次这个操作,就说明n中有一个“1”。

因为n必定要从最近的“1”中借位,才能满足-1操作,否则-1后该数小于0。减1后,所借之位前面不变,自身为0,后面必定是从0全变为1。

然后进行与操作并赋值,就可以将第一个1抹除,num+1。之后重复上述过程,直到n等于0。

在这里插入图片描述

	public static int count3(int n) {
        int num = 0;
        while (n > 0) {
            n = n & (n - 1);
            num++;
        }
        return num;
    }

还有一些分支法,查表法,就是提前把所有情况写出来的一种暴力方法,在此不一一列举了。

如果这篇对你有帮助请点击下方一键三连谢谢大家

扫描二维码关注公众号,回复: 9906321 查看本文章

在这里插入图片描述

发布了41 篇原创文章 · 获赞 94 · 访问量 9562

猜你喜欢

转载自blog.csdn.net/qq_41718454/article/details/104512008