关闭

二进制中有多少个1

标签: 位运算二进制
689人阅读 评论(0) 收藏 举报
分类:

题目描述:计算在一个 32 位的整数的二进制表式中有多少个 1.

样例:给定 32 (100000),返回 1;给定 5 (101),返回 2;给定 1023 (111111111),返回 9

很简单的题目,当然可以先对十进制的整数转换成二进制,再统计1的个数。

但是通过位运算(其实就是通过分析二进制位上0,1的关系,直接对0,1比特位进行运算)我们可以更快地解决问题。

先说一下基本的几种位运算:

1. 与(&):相当于是数学关系中的交,只有全部为真,结果才是真,也就是说,

0 & 1 = 1 & 0 = 0 & 0 = 0; 

1 & 1 = 1 

2. 或(|):相当于求并,有一个真就是真,

0 | 0 = 0

1 | 0 = 0 | 1 = 1 | 1 = 1

3. 异或(^):相同则假,相异则真,

1 ^ 1 = 0 ^ 0 = 0

1 ^ 0 = 0 ^ 1 = 1


当然,还有右移和左移运算,这里不做详细介绍了。以后有机会再同大家分享。

回头看这道题,要统计的是整数的二进制中有多少个1. 那么可以考虑一下这个问题,就是整数和它减去1后的数相比,在二进制的形式中,有什么关系呢?

我发现,有以下两条:

1. 奇数的话,减去1成偶数,二进制形式中,只有最后一位不同(由1变为0)。例如:5:101,4:100

2. 偶数的话,减去1成奇数,二进制形式中,偶数尾巴上的所有0(直到倒数第一个1为止),全部变为1,且倒数第一个1变为0. 例如:142:10100000;141:10011111

好了,这就算是找到规律了,这个规律怎么用呢?我发现,用“与”运算可以产生很奇妙的效果:不论是奇数还是偶数,“与”运算之后,都会是原先的数的二进制中少一个1.

那么思路很清晰了,写一个循环,每次都和减1的值做“与”运算,直到结果等于0,统计循环的次数,就能知道有多少1.

代码如下:

class Solution:
    # @param num: an integer
    # @return: an integer, the number of ones in num
    def countOnes(self, num):
        count = 0
        temp = num
        if num < 0:
            temp = abs(num + 1)
        while temp != 0:
            count += 1
            temp = temp & (temp - 1)
        return count if num >= 0 else (32 - count)
        # write your code here


需要注意的是正负数的二进制问题。7-8行是对负数做的处理。这里,先普及一下负数的二进制是如何生成的,分两步:

1. 取反:就是对这个负数的绝对值按位取反,得到的叫做反码(比如,要计算-2的二进制,就要先对2的二进制按位取反)

2. 加1:取反后,对这个二进制数加1,得到的叫做补码

比如,-24,先对24(二进制数:11000)取反,得到00111;再加1,得到01000

所以,我们设一个负数是a,显然,a - 1的二进制表示就是-a的反码。而用32减去(-a)中1的个数就是(a - 1)中1的个数。因此,求一个负数的二进制中1的个数,可以先对这个数(把他看做a - 1)加1,记为b,再求b的绝对值的二进制表示的1的个数,记为n,32 - n就是最后的答案。

上面的逻辑稍微有点绕,不过仔细想想应该能明白。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:166974次
    • 积分:3708
    • 等级:
    • 排名:第9592名
    • 原创:210篇
    • 转载:0篇
    • 译文:0篇
    • 评论:32条
    博客专栏
    文章分类
    最新评论