首页 > 试题广场 >

二进制中1的个数

[编程题]二进制中1的个数
  • 热度指数:854742 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。

数据范围:
即范围为:
示例1

输入

10

输出

2

说明

十进制中10的32位二进制表示为0000 0000 0000 0000 0000 0000 0000 1010,其中有两个1。       
示例2

输入

-1

输出

32

说明

负数使用补码表示 ,-1的32位二进制表示为1111 1111 1111 1111 1111 1111 1111 1111,其中32个1    
推荐
public class Solution {
    //从n的2进制形式的最右边开始判断是不是1
    /*
    * 该解法如果输入时负数会陷入死循环,
    * 因为负数右移时,在最高位补得是1
    * 二本题最终目的是求1的个数,那么会有无数个
    * 1了。
    */
    //-------------可能陷入死循环的解法---------------------
    public static int NumberOf1_CanNotUse(int n) {
        int count = 0;
        while (n != 0) {
            /*
            * 用1和n进行位与运算,
            * 结果要是为1则n的2进制形式
            * 最右边那位肯定是1,否则为0
            */
            if ((n & 1) == 1) {
                count++;
            }
            //把n的2进制形式往右推一位
            n = n >> 1;
        }
        return count;
    }
    //---------------正解--------------------------------
    //思想:用1(1自身左移运算,其实后来就不是1了)和n的每位进行位与,来判断1的个数
    private static int NumberOf1_low(int n) {
        int count = 0;
        int flag = 1;
        while (flag != 0) {
            if ((n & flag) != 0) {
                count++;
            }
            flag = flag << 1;
        }
        return count;
    }
    //--------------------最优解----------------------------
    public static int NumberOf1(int n) {
        int count = 0;
        while (n != 0) {
            ++count;
            n = (n - 1) & n;
        }
        return count;
    }
    public static void main(String[] args) {
        //使用n=10,二进制形式为1010,则1的个数为2;
        int n = -10;
        System.out.println(n + "的二进制中1的个数:" + NumberOf1(n));
    }
}

编辑于 2015-08-18 23:23:00 回复(148)
Python
Python的负数显示方式是比较怪的:bin(-3) = -0b11,但实际上存储还是补码
题目要求为32位二进制,所以我们需要使用一个满1的32位数进行一个截断(Python是无限位显示)
(2^32=4294967296=0b11111111111111111111111111111111=0xffffffff
来进行按位与操作,来获得负数的补码形式
class Solution:
    def NumberOf1(self, n):
        # write code here
        if n<0:
            n=n&0xffffffff         count=0
        for i in range(32):
#             解法1
#             if n&(1<<i) == 1<<i:
#                 count += 1
#             解法2
            if n != 0 :
                n = (n-1)&n
                count += 1
        return count

发表于 2021-06-12 04:12:42 回复(0)
正数的补码就是自己。负数的补码是:除符合位外,各位取反,然后总体+1】
所以&0xffffffff即可
# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        n = n & 0xffffffff
        n = bin(n)[2:]
        nums = 0
        for i in n:
            if i =='1':
                nums +=1
        return nums
        # write code here

发表于 2021-01-30 12:23:19 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        if n == 0:
            return 0
        if n < 0:
            # 取绝对值
            n = abs(n)
            # 取反码,用32位的1与原码异或
            n = n ^ 2 ** 32 -1
            # 补码 = 反码 + 1
            n += 1
        
        count = 0
        while n:
            # 与1做与运算,判断最低位是否为1
            if n & 1:
                count += 1
            # 每轮都将二进制数右移一位,直到n为0
            n = n >> 1 
        return count

发表于 2020-08-15 01:37:56 回复(0)
class Solution:
    def NumberOf1(self, n):
        # write code here
        # 十进制转化为二进制
        # 2整除十进制数字取余,逆序排列
        # 是最简单的机器数表示法。用最高位表示符号位,‘1’表示负号,‘0’表示正号。其他位存放该数的二进制的绝对值。
        # 正数的反码还是等于原码, 负数的反码就是他的原码除符号位外,按位取反。
        # 正数的补码等于他的原码, 负数的补码等于反码+1。
        F_list = []
        L_list = []
        q = n
        count = 0
        if n> 0:
            while q>0 : 
                a = q // 2 
                r = q % 2
                if r == 1:
                    count += 1
                F_list.append(r)
                q = a
            return count
        elif n == 0:
            return 0
        else :
            n = bin(n&0xffffffff) #负数的补码 s
            s = str(n)
            for i in s:
                if i == '1':
                    count +=1
            return count
           

发表于 2020-08-06 22:04:28 回复(0)
class Solution:
    def potn(self, n):
        sum1 = 0
        flg = 0
        while n:
            a = n % 2
            n = n // 2
            if a == 1:
                sum1 += 1
            flg += 1
        return sum1, flg
       
    def NumberOf1(self, n):
        # write code here
        sum1 = 0
        flg = 0
       
        if n >= 0:
            sum2, flg2 = self.potn(n)
            return sum2
           
        else:
            num = abs(n)
            sum2, flg2 = self.potn(num)
            b = 32 - flg2 + sum2
            return b
发表于 2020-08-06 19:58:00 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        count = 0
        for i in range(0, 32):
            if (n>>i & 1):
                count += 1
        return count

发表于 2020-07-23 17:27:43 回复(0)

python简洁版:

class Solution:
    def NumberOf1(self, n):
        res=sum([1 if n&(1<<i)>0 else 0 for i in range(31)])
        return res if n>=0 else res+1

思路来自排名第一的回答的第一个思路,用1左移i次的结果与数字n做&操作看是否大于0,另外,python的int支持大数,没有32位精度限制,所以自己手动为负数加上符号位的1

编辑于 2020-05-13 14:44:42 回复(0)
  • 方法一:转换成二进制(字符串),直接数“1”的个数
  • 方法二: 位运算:mask=1<<i,其中i表示向左移动几位,右边加0,并与原来结果相与。原数位为1,相与结果为1;原数位为0,相与结果为0(if那句话)。
  • 方法三:骚操作:n与n-1相与,每次循环可以将n中的一个1去掉,直到所有1去掉变为0。
class Solution:
    def NumberOf1(self, n):
        # write code here
        '''
        # 方法一
        n = n & 0xFFFFFFFF
        bin_num = bin(n)
        count=0
        for i in bin_num:
            if i == '1':
                count+=1
        return count
        
        # 方法二
        n = n & 0xFFFFFFFF
        count = 0
        for i in range(32):
            mask = 1 << i
            if mask & n !=0:
                count+=1
        return count
        '''
        # 方法三
        n = n & 0xFFFFFFFF
        count = 0
        while n:
            n = n&(n-1)
            count += 1
        return count


编辑于 2020-03-16 16:21:38 回复(0)

判断n的二进制表示中1的个数
将n依次与flag = 1,2,3,4,5..进行与运算
必须对flag进行一定的限制,不然会一直循环下去:

  • n>=0时,flag <= flag即可
  • n<0时,先将n与0xFFFFFFFF作与运算,转正【真的是这样吗?】
# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        """

        :param n:
        :return:
        """
        flag = 1
        cnt = 0
        if  n < 0:
            n = n&0xFFFFFFFF
        while(flag and flag <= n):
            if n & flag:
                cnt += 1
            flag = flag << 1
        return cnt


s = Solution()
cnt = s.NumberOf1(-1)
print(cnt)
发表于 2020-02-24 15:51:38 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        #按位“与” :两个位置都为1才为1
        #方法一:转化为字符串
        #正数:源码、反码、补码一致;负数:源码、反码、补码不同
        '''
        n = 0xFFFFFFFF & n #只计算32位,实际上不只是有32位(考虑当n为负数时)
        count = 0
        for i in str(bin(n)):
            if i == "1":
                count += 1
        return count
        '''
        
        #方法二:用mask与每个位置与,求每个位置是否为1
        '''
        count = 0
        n = 0xFFFFFFFF & n
        for i in range(32):
            mask = 1 << i
            if n & mask != 0:
                count += 1
        return count
        '''
        #方法三:n = n&(n-1) 装逼式写法
        #101101 & 101100 = 101100  count = 1
        #101100 & 101011 = 101000  count = 2
        #101000 & 100111 = 100000  count = 3
        #100000 & 011111 = 000000  count = 4
        count = 0
        while n:
            n = 0xffffffff & n
            n = n&(n-1)
            count += 1
        return count

发表于 2019-12-26 11:01:58 回复(0)
# -*- coding:utf-8 -*-
# 如果一个整数不为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,就可以进行多少次这样的操作。


class Solution:
    def NumberOf1(self, n):
        # write code here
        count = 0
        if n < 0:
            n = n & 0xffffffff
        while n != 0:
            n = n & (n - 1)
            count += 1

        return count

发表于 2019-12-09 22:45:09 回复(0)
Python Solution:

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        n = 0xFFFFFFFF & n
        stri = str(bin(n).replace('0b', ''))
        count = 0
        for i in stri:
            if i =='1':
                count += 1
        return count
        
        
        
        #return bin(n).replace('0b','').count('1')

发表于 2019-12-06 20:50:16 回复(1)
别问我为啥,我也不知道,可能是一种求负数的二进制补码固定写法吧,就是用n&0xffffffff。对于需要多少位,就看题目要求更改f的个数就行了
发表于 2019-10-30 20:32:22 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        if n == 0:
            return 0

        ct = 0
        if n < 0:
            n += 2**32  
        while n > 0:
            if n & 1 == 1:
                ct += 1
            n >>= 1
        return ct
发表于 2019-10-27 16:44:08 回复(0)
python是一种动态的语言,其中的整数不会溢出,所有当n为负数时,可以理解为(无穷多个'0'+其绝对值)的补码运算,即2转化为二进制是000000000000000000000000000000000000.....10,-2的补码就是各位取反再加一,答案是111111111111111111111111111...01。所以要先和0xffffffff进行按位与,这样大于32位的'1'就会溢出,变成标准的补码格式。
n和n-1进行按位与使每次最右边的’1‘变成’0‘,统计其次数,最后全部变成零则结束循环。
# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        if n<0:
            n=n&0xffffffff
        res=0
        while n:
            res+=1
            n=n&(n-1)
        return res


发表于 2019-10-18 19:43:32 回复(0)

注意:这里的整数用32位存储。

python处理时,通过与上0xff...ff可以将有符号数变成无符号数。
负数的补码,是对应正数取反+1得到:例如9的二进制是1001,对应的补码就是10110 + 1 = 10111(最高位是符号位),用32位存储的结果就是 (28个1)0111

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        BiStr = bin(n)
        if n<0:
            n = -n
            BiStr = bin((~n&((1<<32)-1))+1)
        return BiStr.replace('0b', '').count('1')
发表于 2019-10-09 19:34:49 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        if n>=0:
            return bin(n).count('1')
        return bin(int(bin(-n)[2:].zfill(32).replace('0','a').replace('1','0').replace('a','1'),2)+1).count('1')
😂python里面也没32位这个概念吧,太坑了
发表于 2019-10-04 00:04:23 回复(0)
Python 解法
class Solution:
    def NumberOf1(self, n):
        # write code here
        if n == 0:
            return 0
        n = n & 0xffffffff    # 若n > 0, n不变;若n<0,n = n的补码
        bit = []
        while n > 0:
            bit.insert(0,n%2)
            n = n // 2
        return sum(bit)
发表于 2019-09-25 11:04:22 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        count = 0
        if n<0 :
            n = n&(0xffffffff)
        while n!=0 :
            n = n&(n-1)
            count = count + 1 
        return count
Hint:
python表示补码需要手动转换
编辑于 2019-09-22 00:28:31 回复(0)

【剑指offer】二进制中1的个数

我的思路:

如果是正数,直接计数1的个数
如果是负数,转换成补码,然后计数1的个数
转成补码:
先把数字二进制形式下的位数补到32位,使用字符串的内置函数zfill(位数),接着取反+1
如果数字的二进制位数本身就有32位,那么不需要额外+1(符号位)
其他进制转成十进制:
int(字符串,其他进制的模)

注意:

Java和c++里,负数会自动转成补码,python不会,所以需要自己转换

代码:

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        l=''
        res=0
        if n<0:
            n_bin=bin(n)[3:].zfill(32)
            print(n_bin)
            for i in n_bin:
                if i=='1':
                    temp='0'
                else:
                    temp='1'
                l+=temp
            temp=bin(int(l,2)+1)[2:]
            if len(temp)==32:
                res = temp.count('1')
            else:
                res=1+temp.count('1')
        else:
            res=bin(n)[2:].count('1')
        return res

更好的思路(参考评论区):

补码本质上是同余数论(https://www.zhihu.com/question/21511392)的产物,
(c++和java):
    1.n=n&0xffffffff(把整数转成补码形式)
    2.while n!=0:    n=n&(n-1)    count++(一个整数与该整数右移一位的数做与操作,得到的是该整数最右边的1变成0的数)有多少个1,就会进行多少次操作,通过这个得知一个整数补码中1的个数)
(python):
    bin(n&0xffffffff).count('1')

代码:

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        return bin(n&0xffffffff).count('1')
编辑于 2019-08-29 09:31:42 回复(0)

问题信息

难度:
66条回答 228481浏览

热门推荐

通过挑战的用户

查看代码