剑指offer---二进制中1的个数

题目10:二进制中1的个数(leetcode链接:https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/

一、问题描述

题目:统计二进制中1的个数。

          写一个函数返回参数二进制中 1 的个数。

示例: 15    0000 1111    4 个 1

             -1   ................     32个1

示例分析:

二进制负数,在内存中以其补码的方式进行存储。
-1的原码:10000000 00000000 00000000 00000001(第一位为符号位)
-1的反码:11111111 11111111 11111111 11111110
-1的补码:11111111 11111111 11111111 11111111
         所以,-1的二进制中有32个1

原码、补码、反码
    原码:数的二进制表示
    反码:原码除符号位外的位数按位取反
    补码:反码 + 1

二、问题分析及C语言程序描述

方法1:可能会引起死循环的解法

判断所给数的最后一位是不是1,如果是count++,而判断该数的最后一位是否为1只需要将该数与1相与如果结果是1表明最后一位是1,然后将该数右移一位继续判断最后一位。

缺陷分析:右移运算符,如果目标数是正数则右移n位为去掉该数的最右边的n位左边补n个0;如果目标数是负数,则右移n位为去掉最右边的n位左边补n个1,因此对于一个负数如果采取上述方法,每次给左边补1,就会陷入死循环。而如果把右移改成/2运算,在计算机中除法的运算效率比右移的运算效率低的多。

方法2

每次右移时,如果是负数会陷入死循环。如果最右边1位是1该数与1相与结果是1,如果最右边的第二位是1该数与2相与结果为2......如果最左边一位是1,该数与2^31相与结果为2^31.因此可以使用for循环,进行32 次相与判断每位是否为1.

int hammingWeight(uint32_t n) {
    int count = 0;
    unsigned int flag = 1;
    while(flag){
        if(n&flag){
            count++;
        }
        flag = flag << 1;
    }
    return count;
}

方法3

方法2中,无论所给数中有几个1,都需要进行32次判断。对于一个整数,减去1后,我们发现二进制中最右边的一个1变成了0,如果这个1的右边还有0则会变成1,例1100-1 = 1011,而一个整数减去1在与原整数相与,会将整数的最右边一位1变成0,例1100 & 1011 = 1000,而1100最右边一位1去掉结果为1000.我们重复这样的操作,直到该整数变成0,那么整数中有几个1就需要进行几次这样的操作。因此,这种方法中整数中有几个1就需要判断几次。

int hammingWeight(uint32_t n) {
    int count = 0;
    while(n){
        ++count;
        n = n&(n-1);
    }
    return count;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂嘚程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值