给定一个非常长的字节序列如何高效的统计1的个数

来源:互联网 发布:手游源码交易 编辑:程序博客网 时间:2024/04/29 00:51

题目:“给定一个非常长的字节序列(假设有十亿或万亿),如何高效的统计1的个数(也就是说,在整个序列中有多少个位的值为1?)”

解答:

统计一个字节序列中1的个数,我首先想到的是最简单,把这个数每次右移一位,然后与0x01逻辑与进行统计,相当于总共将真个字节序列遍历了一遍。然而仔细想想,一个十亿或万亿的字节序列,能存到一个数(或称为变量)中?必然不可以,因此这是陷阱所在。

深入思考,既然是字节序列,那我解释成任何数据类型都是可以的啊,我可以按照32位机器的int大小,比如4个字节来把这么长的字节序列读到一个个的Int值中,然后统计每个int值的位中1的个数,加起来就可以了。

由此题目变成了这样:

“给定十亿或万亿个int数字,求他们所有位中为1的个数的总和。”

这样就简单非常多了,首先求一个int值中1的个数很简单,要么移位与0x01与,要么辗转相除看是奇数还是偶数。

重点在于,这里有十亿或万亿个int数字,怎样做才能优化算法呢?这里提出3中优化方法:

1、int有4个字节32位整数,那么我建立一个2的32次方的表,每个表项是一个数字和该数字1的位数,我就不用计算了只是查表,缺点是2的32次方个表项,每个表项8个字节(数字,1的位数),32GB的表大的惊人吧。有人说那我其实只需要一个数组,数组大小为2的32次方,每个下标存放一个int表示1的位数。这样也得4*(2的32次方)B=16GB啊亲

2、缓存。每计算一个数字的位数,就将该(数字、位数)键值对存起来,下次计算前,先查表,这个表最好用哈希,这样会节省非常多的时间。

3、先统计每个Int数字出现了多少次,然后挨个计算位数,乘以出现的次数,最后相加,这种方法很好了。

0 0
原创粉丝点击