如何以最优时间复杂度得出——判断一个字节内的整数的二进制形式中的1个数

声明:

1、本文全文为半香仙笛(Woody.c)原创

2、如果需要转载本文,请注明出处:http://blog.csdn.net/mcg890414/archive/2010/09/08/5870044.aspx

3、如果需要和笔者交流,请邮件至mcg890414@163.com

 

Thinking in C。。

 

最近每日比较大量的工作,是为了找工作而做面试题。

做了许多智力型的面试题,觉得自己思维,打个85+分不为过吧,毕竟还是智商超过140的人。

昨日看到一道关于“如何以最优时间复杂度得出——判断一个字节内的整数的二进制形式中的1个数”。

输入:

  正整型,1个。要求在一个字节内(0~255)。

输出:

  整形,1个。是输入的数的二进制形式中1的个数(应该在0~8之间)。

示例——

输入:

  33

输出:

  2

 

题目出得很好。

 

我有思考。

最初想,循环右移。当结果不为0得失后继续右移。并计数。

写出代码如下:

这个算法,时间复杂度约为O(m),也就是说,需要循环的次数,为最高一个1所在位数的位置所决定,越靠左,循环次数越高,最多可达8次。

 

我觉得,一般的程序员都能想到这个算法,所以,面试题肯定不会给这么简单的答案。

继续思考。。。

我想,有没有一种算法,能够不由某一个1决定,而由所有的1决定呢?也就是说,数n次,n是这个二进制中1的个数?

所以,有了下面的算法:

读起来是不是有些费解?呵呵,没关系,我来解释一下,如果你已经理解了,请跳过这段解释。

这个算法把二进制中的最后一个1变为0,若其不是最后一位,将其之后的所有0变为1(n-1的功效,强大吧),然后拿这个结果来位与。这样的话,每次位与就消除最后一个1。

没明白?好,我们来看个例子:

加入我们有输入:

11001001

第一次减1,得到

11001000

位与结果:

        11001001

 &     11001000

--------------------

        11001000

第二次,减1,得到

11000111

位与结果:

        11001000

&      11000111

-------------------------

        11000000

第三次,减1。,得到

10111111

位与结果

        11000000

&      10111111

-------------------------

        10000000

第四次,减1,得到

01111111

位与结果

        10000000

&      01111111

--------------------------

        00000000

结束。

计数4次,得到返回结果为4。

你懂了么?

如果你还没懂,请给我邮件:mcg890414@163.com

 

好了,第二个算法,较第一个时间复杂度更优。

不过,我们还可以以空间换时间,不过,如果给的输入不是8位,每多1位,需要的工作就要大两倍。

我们来看时间复杂度为O(1)的算法:

这个算法有点暴力,可以提前用之前的算法运算出来一个表,然后放入之前写好的一个数组中,直接输出这个输入作为下标的数组元素即可。

当然,这个算法是用空间来换时间的。作为思维训练是可以的,但是真正的开发中,没有人会推荐你使用这个算法。

 

好了,先聊到这,Then....

你有更好的算法么?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值