2.1 求二进制数中的1的个数

题意:8bit无符号整型变量N,求其中二进制位中1的个数。

解法一,笨方法,使用除法和模运算,即使编译器能帮人优化,但解法的思想并没有走到位这个概念上去。

解法二是笔者首先想到的解法,即与0x01进行与运算,判断是否为1,之后再右移,这个方法清晰明了,虽说复杂度为O(log2N)级别,但和再小的复杂度差别不大。

解法三的确是一个非常巧妙的方法,复杂度只和1的个数有关,每次循环都消去最低位的1,最终得到1的个数。

解法四有点走火入魔了,写代码都累死,说是空间换时间,写代码的时间不算?

解法五可以说是解法四的改良版本,直接hashtable就OK,算是先把结果算好存着。

若改成32位的DWORD,五种方法都直接能用,前三个什么都不用改,直接把变量放进去就行,后两个解法也不需要去扩展table的大小,把DWORD拆成4个BYTE来算就行。

2.2 不要被阶乘吓倒

题意:两个问题,一是N!末尾0的个数,二是N!二进制最低位1的位置。

先说问题一,解法一和解法二都是从找N!中因数5的个数出发的,为什么5的个数决定后面0的个数呢?

因为5*2=10,而每连续的10个数里面,因数5出现2次,而因数2会出现5次,因此,统计5的因数个数就行了。

解法一暴力搜索,枚举1到N,模运算统计所有因数为5的数字的个数。解法二很有意思,不过书上说的不太好理解。

我知道2进制和10进制,那么是否可以写成5进制呢?那是当然的。5进制满5进1,所以除了最低位,其他所有位上的数字都是5的倍数,可以写成如下形式:

55*2+54*1+53*0+52*4+51*1+50*3=(210413)5=N

我们在做二进制位操作的时候可以移位,这个5进制的,没有先天优势,只能用除法了,每次除以5,把因素5的个数找出来即可。

代码写出来的效果和书上一样。

问题二可以等同于为,求N!中质因数2的个数。

解法一和问题一的解法二思路一样,只是得到0的个数之后,需要加1,这才是最低位1的位置。

解法二利用了一个规律:N!含有质因数2的个数,等于N前去N的二进制中1的数目。笔者感觉这个规律是比较难以快速发现的。

posted on 2012-10-26 15:51  罗辑  阅读(192)  评论(0编辑  收藏  举报