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

二进制1计数法
本文介绍了一种计算整数二进制表示中1的个数的方法,包括正数和负数的处理方式。正数直接转换为二进制并计数,负数通过补码计算。详细解析了补码的计算过程,并提供了C++代码实现。

题目描述

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

思路分享

此题在熟练掌握计组课上的编码基础后很好解决,难度不大。
设输入的十进制数为n,二进制形式的1个数为cnt。

  • 正数实现

    正数按照常见的10转2进制方法实现即可:求n%2 = 1 则cnt加1;再另n = n / 2(整除);循环直至n == 0.

  • 负数实现
    负数稍微麻烦一些,按照定义,负数的补码为2^32 - |负数|的差的原码。
    题设的int变量大小为32位,以-1的补码为例:
    2^32原码为1 0000 0000 0000 0000 0000 0000 0000 0000;
    |-1| = 1,原码为0000 0000 0000 0000 0000 0000 0000 0001;
    则2^32 -1= 1111 1111 1111 1111 1111 1111 1111 1111;
    由于int变量32位的限制,int无法表达2^32 这一数值。
    因此只计算至与|n|最接近且比|n|大的2次幂整数,设它为full, 如:
    十进制8(1000)的full为16=2^4(10000);
    十进制17(10001)的full为32=2^5(100000);
    full-|n|的差得到的正数的原码即为n的补码(低位部分)。
    如:2^5 - 17 = 100000 - 10001 = 01111
    按照补码的规定,32位表达时,负数原码为0的高位全部转为1,因此-17的补码表示为:
    1111 1111 1111 1111 1111 1111 1110 1111
    即-17的补码高32-5=27位全为1.
    特别的,有-2^32(即-2147483648)补码为:
    1000 0000 0000 0000 0000 0000 0000 0000

代码实现

class Solution {
public:
     int  NumberOf1(int n) {
         if(n==0) return 0;
         if(n==-2147483648) return 1;
         int cnt;
         if(n > 0){
             while(n >= 1){
                 if(n%2 == 1) cnt++;
                 n /= 2;
             } 
         }
         if(n < 0){
             int temp = 0-n, full=1, time=0;
             //full是最近的2次幂数,time是log2(full)
             while(temp >= 1) {
                 temp/=2;
                 full*=2;
                 time++;
             }
             //full减去这个负数得到的就是补码
             n = full + n;
             while(n >= 1){
                 if(n%2 == 1) cnt++;
                 n /= 2;
             } 
             //由于int为32位,所以比full更高的位都要变成1
             cnt = cnt + (32 - time);
         }
         return cnt;
     }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值