资讯专栏INFORMATION COLUMN

二进制中1的个数

zsirfs / 3114人阅读

摘要:题目输入一个数不管是几进制,输出这个数二进制表示中的个数。代码如下相当于这个解法中循环次数等于目标整数二进制的位数,位整数就需要循环次,方案三给出目标整数中有几个就只循环几次的方案。举个例子一个二进制数,从右边数起第三位是处于最右边的一个。

题目:输入一个数(不管是几进制),输出这个数二进制表示中1的个数。比如输入 9 应该输出 2 ;输入0x1F(31) 应该输出 5 。(16进制表示是在前面加 0x )

方案一:

我最开始的想法是把这个数转化成二进制,因为之前做过十进制转二进制所以理所应当的这么想了,最后感觉不太对,要这么写那的写几个进制转换类啊,而且效率不高。

方案二:

然后看了一下书,书上的做法很巧妙:先查看目标数字末尾位是0还是1,这可以通过与一个1做与运算得到结果,然后把目标数字右移一位,继续与1做与,声明一个计数器count,持续加就好。
不过也给出了缺陷,缺陷在于如果目标数字是负数(负数的符号位也要算进总的1的个数里)不光没法的到正确结果,还会让陷入死循环:把负数0x8000右移一位,其实是变成了0xc000,多移几次就变成0xffff然后
死循环了,因为左移和右移是基于这样的原则:
                左移时最左边的n位被丢弃,同时在最右边补上n个0。
                右移时如果是正数补0,负数在最左边补1.

所以更新方案:把1左移,循环一次就左移一次,这样目标数每一位的1就都不会放过,与运算每得到一个1就count++。反正最后1移到最后就溢出了变成0000000000,这就是循环中止条件。
代码如下:

public class Jianzhi{
    public static void main(String[] args){
        int num = 0xFF ;  //相当于int num = 31 ;
        int flag = 1 ;
        int count = 0 ;
        while( flag != 0 ){
            if( (num&flag) != 0 ){
                count++ ;
            }
            flag = flag << 1 ;
        }
        System.out.print(count);
    }
}

这个解法中循环次数等于目标整数二进制的位数,32位整数就需要循环32次,方案三给出目标整数中有几个1就只循环几次的方案。

方案三:
如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。

基于这种思想有如下代码:

public class Jianzhi{
    public static void main(String[] args){
        int num = 0xFF ;  //相当于int num = 31 ;
        int flag = num-1 ;
        int count = 0 ;
        while(num != 0 ){
            num = num & flag ;
            flag = num - 1 ;
            count ++ ;
        }
        System.out.print(count);
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71395.html

相关文章

  • 【剑指offer】一个数进制序列1个数

    摘要:图解第二种算法图解代码示例算法如果为真,说明拿到的是二进制序列的个数为算法为的时候说明已经拿完了,循环终止二进制序列中的个数以上代码,还可做优化在此仅作参考,若有更好的算法,还望能够私信告知,多谢各位。 ✨前言✨: 算法是一个程序员的内功,能很好的体现程序员的编程思维,通过学习和掌握常见的算...

    weknow619 评论0 收藏0
  • 剑指offer:进制1个数(Java)

    摘要:问题描述输入一个整数,输出该数二进制表示中的个数。其中负数用补码表示。思路方法将二进制变成字符数组,遍历数组统计的个数,这种办法不需要考虑正负数。遍历字符数组,统计的个数判断该位是否是,如果是就,否则执行下一次循环。的二进制表示想右移一位。 1.问题描述 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 2.思路 方法1:将二进制变成字符数组,遍历数组统计1的个数,这...

    lifesimple 评论0 收藏0
  • 别人家面试题:统计“1个数

    摘要:长话短说,让我们来看一道题统计的个数给定一个非负整数,对于任意,,计算的值对应的二进制数中的个数,将这些结果返回为一个数组。第二版本的时间复杂度是最后版本的时间复杂度是,是的二进制数中的的个数,介于之间。 小胡子哥@Barret李靖给我推荐了一个写算法刷题的地方leetcode.com,没有ACM那么难,但题目很有趣。而且据说这些题目都来源于一些公司的面试题。好吧,解解别人公司的面试题...

    SQC 评论0 收藏0
  • 【Redis学习笔记】bitcount分析

    摘要:二算法思路执行这一命令的过程,核心是求二进制数中的个数。筛出了奇数序列上的,筛出了偶数序列上的相加后的值,代表了这上的个数此时对于的二进制数据,我们已经按分好了组,每存放着的是该组的个数,现在把这四组数加起来即可,即实现。 顺风车运营研发团队 熊浩含一、命令简介BITCOUNT key [start] [end] redis计算给定字符串中,被设置为 1 的比特位的数量。 redis>...

    int64 评论0 收藏0
  • 数据表示:原码、反码、补码、移码以及浮点数运算

    摘要:而相应的,科学家们又提出了补码这一概念。因此在计算机中,为了避免运算错误,都是采用的补码进行加减法运算。原码反码补码移码数值表示范围在开始了解数值的表示范围之前,我们先来了解下什么叫做定点。 ...

    cnTomato 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<