剑指offer 面试题 (二进制中 1 的个数)(4)

来源:互联网 发布:c语言或符号 编辑:程序博客网 时间:2024/05/01 06:15

# 面试题:  求一个整数二进制中 1 的个数?


/*


题目:  请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。

例如把 9 表示为二进制是 1001, 有两个 1;因此,如果输入 9,则输出 2;


*/


题目分析:

                  学过计算机机基础的同学应该都知道,在计算机中的存储都是以二进制形式存在的! 那么求出一个整数

二进制中 1 的个数,当然不在话下了, 看到这道题的的时候应该都是信息满满; 注意: 当面试的时候遇到这道题,

就得仔细思考一下了,面试官不会那么无聊吧!  无非就是把整数变成二进制,用计数器加出来其中 1 的个数嘛1 !

对,没问题,那么问题就在于实现时的细节了,老话常说:细节决定成败!


算法选择:  

                 已经很明确了,选择计数器,循环; 那么我们来看下面实现的几个版本有什么不同!


代码实现: @算法 (一)>>>>将num 的二进制和1进行按位&, 则&操作两个都为 1 结果才为1 ,否则为 0;

                    用每次结果为1时 ,count+1;


int NumberOf1(num){int count = 0;//计数器while(num){/* 这块的num&1 相当于 num%2;num>>1相当于num / 2; 但是移位运算要比除法运算的效率高得多! */if(num & 1)count++;num = num>>1;}return count;}


代码反思: 代码写到这,并不代表就完事了,还要测试一下啊,多测试几组数据你就会发现,输入 -1,的时候会死循

环,这是因为负数的符号位是 1 (这个在计算机基础里面有); 并不是你把最高位的 1 右移之后就变成 0 了;例

如:  10000000 00000000 0000000 00000001  这是(-1)
         11000000 00000000 0000000 00000000  (-1)右移一位之后最高位的 1 不变;

所以程序会死循环;那么就有了下面的改进:


代码实现:  @算法(二)  设置一个标志位,移动标志位不移动 num 本身;即 另flag=1,然后num 和 flag按位&
                   
                     如果&的结果是1 .则count++;   每次&完,flag左移一位;就解决了负数问题;例如:进行一次循环

num = -1:   10000000 00000000 0000000 00000001 ;

flag = 1  : 00000000 00000000 0000000 00000001 ;

num&flag: 00000000 00000000 0000000 00000001 ;

flag<<=1:   00000000 00000000 0000000 00000010  ;          

然后进行下次循环flag和num 的第31位进行比较,一次类推循环32次!


int NumberOf1(num){int count = 0;//计数器int flag = 1;while(flag)//循环32次后flag自动变为0;{if(num & flag)count++;flag = flag << 1;}return count;}

@与此类似的for循环32次的代码如下:
       
int NumberOf1(num){int count = 0;//计数器int i =0;for(;i<32;i++){if(num & 1)count++;num>>=1;}return count;}

ps: 写到这里,是不是觉得应该完了吧!  就这么一个题!   but,答案是否定的, 假面试官告诉你,觉得还有有些麻

烦,让你改一下,num中有几个 1 就循环几次;

你该怎么做?

/*

这下就得好好开动脑子了,这才有些算法的味道出来了;

那么我们就开始分析吧!   首先,先例一个数出来吧,比如 7;二进制为: .....0111; 前面的0省略了,反正人家就要

求有几个1循环几次(别忘了负数)减去一个 1试试,变成: .....0110; 再将num-1  和  num  按位&一下是不是把右

边的一个1变为了 0;  那么规律来了,只要num不为0,那么它总有一位是1;那就count++;接着将 num & num-1;  因

为你已经count++了,所以就应该让num少一个 1 ;  循环起来;


*/

代码实现:  @算法(三)   有几个1 循环几次;




int NumberOf1(num){int count = 0;//计数器while(num){++count;num = num & (num - 1);}return count;}


over !

thanks!


                  

 



1 0