声明:
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....
你有更好的算法么?