首先,严厉批评某些博主,什么玩意儿啊。
自己都没弄明白,自己都不知道自己写的什么东西,就好为人师。
自己写的那些文章语言很精美,但是代码及思路逻辑不同,(剧透一下)你都用位图标记了,
和40亿数据量有毛线关系,叭叭儿说半天,我还以为是我的问题。。。
还腾讯的面试题,还腾讯的朋友,你腾讯的朋友也是老了八辈子霉了,跟你做朋友
题目: 有40亿QQ号,但是只有1G的内存,请问:如何对这40亿QQ号进行去重
分析: 假设内存够用
- 我们最笨的也是嵌套循环,将所有的QQ号拿出来,再遍历QQ号,将每一个QQ号对比,遇到相同的剔除;
- 或者有聪明的小伙伴知道使用Set进行规整,将所有的QQ号利用数据结构剔除;
- 又或者有使用流式处理熟练的小伙伴一个distant进行数据处理
但是加上了内存限制,上面的操作就无法实现了。可以自行计算40亿的QQ号有多大。
要想解决问题首先要明白问题的关键矛盾点。
上面的问题无一不在使用内存将所有数据保存下来。那解决问题就是两点了,一点是利用数据结构来修改保存方式使其使用最小的内存结构,一种是使用算法来优化计算内存。
其实我看过的文章中说的位图我没用过,也没研究过,感谢这些文章给我提供了新思路,这个思路确实是最优解,很棒(但是我感觉好多博主自己不知道),如果我的理解有问题,想法有问题;欢迎私信我,或者评论区找我。
我先说说我的思路
分段算法
我的想法很简单,我们不是没法对数据进行全量download之后对比么,那么我们就分段对比,当然这是我们可以对数据进行有效排序的前提,我们按照一定的顺序将数据分页取出,取出一定大小的,内存可以容纳的数据。再根据无内存限制的几个方法进行去重,当然,这种方式必然面临着多次IO,所以会有查询慢,多次去重得问题,但却是可以解决。我在4年前解决过一个2亿去重慢的问题,当时是一个树节点去重,我就是使用的类似的方法去重的,我可以负责任的说,很慢(HashSet可以快一点,但是遍历就很慢了)。
位图
我理解位图是什么结构呢?
BitMap(位图)是一种非常高效的数据结构,特别适合处理大规模数据的去重和查询问题。它的基本思想是使用一个bit位来表示一个数字是否存在。
比如我有一个3459 那么位图的存储应该是
| 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 |
但是,3549、5439、9534等不都是这么个表达么?所以,位图不是这么用的吧?在题设中我理解这个位图应该这么使用(好多博主就是那种每位都标记在位图中,咱甚至不知道人家是怎么去重的):
假设我们有一个QQ号为763402261,我们不能将每一位按照标注在数字位图中,而是将其看成一个整体,假设最大的QQ是999999999,那么最大的位图也应该是9999999999,也就是我们需要一个BiyMap的大小为10000000000,而QQ就在763402262位上。
接下来我们将数据分段检索,再将数据在固定位图位置上标记,遇到已经标注为1的就去掉,很容易就可以帮40亿数据去重了,要知道我们只是用了10亿个0/1位,这要小得多(按照一个0/1位算作一个字节,就是1G不到)。
当然我不清楚我理解的对不对,我只知道这么做是有意义的,毕竟我没实操过代码,没观测过内存大小,更没有看了一下BitMap的源码,如果我理解是错的,请各位同学指正。
我写这篇文章我只是很反感有些人为了流量瞎写。我也写博客,我的主场在csdn,我深刻知道一篇文章是需要大家不断指正修改的,但是初版是你能理解的,逻辑明确的这样,这样才能对新手有意义,才能让大佬指正,不是瞎写一通,云里雾里,似有非有,做的一手狗屁学问。毕竟做技术人员的,特么的怎么能得过且过呢?