利用bitmap处理海量数据问题:43亿QQ号所占内存大小为什么是512M?40亿个QQ号如何去重?
?參考:
- 騰訊43億QQ號碼用完后怎么辦?
- 騰訊三面:40億個QQ號碼如何去重
一、背景:
首先,明確兩點:
- QQ號是 unsigned int 類型(4字節無符號整數,共32bit), 也就是說 QQ號的取值范圍是:[0,232?1]\color{blue}{[0, 232 - 1]}[0,232?1]。
- QQ號是一個長度為10位的整數,大約是43億,這也是QQ號碼的理論最大值。
- QQ號碼的最小值是 10001, 為什么tx要做這種限制呢?僅僅是早期的一個設定而已。
二、43億QQ號所占內存大小計算:
其次,43億QQ號所占內存大小是多少呢?512M!
- 一個 unsigned int 類型數據可以標識 0 ~ 31 這32個整數的存在與否(4Byte,0 ~ 31 )
- 兩個 unsigned int 類型數據可以標識 0 ~ 64 這64個整數的存在與否(8Byte,0 ~ 64 )
又因為QQ號是 unsigned int 類型(無符號整數,4Byte,32位),也就是說 QQ號的取值范圍是:[0,232?1]\color{blue}{[0, 232 - 1]}[0,232?1]。
因此可對 232 次方范圍內的QQ號所占大小進行推導:
綜上,用 232 / 32 來表示:0 ~ 232-1(232 位) 能包含多少個 0 ~ 31(32位) 范圍的塊。并且每個 0 ~ 31(32位) 的塊兒大小為4字節,因此 232 / 32 × 4字節 的結果就是 0 ~ 232-1 范圍所占字節的總大小,也就是 43億 QQ號所占字節總大小。
232位 / 32位 × 4字節 / 1024 / 1024 = 512M\color{blue}{512M}512M(1M=1024KB,1KB=1024Byte)
由此可見,512M的內存大小,就可以用來標識所有QQ號的存在與否。
三、bitmap的具體實現:
- 把所有 bitMap 位數組依次拼接后可表示 0 ~ 232 范圍內43億的數,所以足夠存儲40億不重復的賬號了
- bitmap數組中的一個uint32類型元素,由4字節組成(每個字節占8位):{[8位][8位][8位][8位]} {[8位][8位][8位][8位]} {[8位][8位][8位][8位]} {[8位][8位][8位][8位]} …
- 如:[0 1 2 3 4 5 6 7] [8 9 10 11 12 13 14 15] [16 17 18 19 20 21 22 23] [24 25 26 27 28 29 30 31] … [...] [...] [...] [... 40億]
- 共需 40億/8位 = 5億字節,5億字節/4字節 = 1.25億 個uint32類型元素數組來串聯拼接表示(uint32類型大小占4字節),所占內存大小為:4000000000/8/1024/1024 ≈ 477M\color{blue}{477M}477M
- 還原qq號(數組下標從0開始):當前第block塊數 * 每個uint32 block塊的固定大小為32 + 當前block塊內的偏移量余數 yushu
- 每次新增QQ號時,都只需要在 bitMap[block] 的結果基礎上繼續進行異或 ^ 運算即可 ~
- 比如原本"QQ號=9(二進制表示 1 0000 0000,位下標為 9)“是有值的,現在又新增了"qq號=10(二進制表示 10 0000 0000,位下標為 10)”
- 那么9和10相異或后得: 1 0000 0000 ^ 10 0000 0000 = 11 0000 0000,表示第 9 位和第 10 位的QQ號都有值了
- 0x1<<(yuShu-1):比如原本"QQ號=9"時,那就把 0x1 左移8位,即:0x1 << 8,得到 100000000,最后從右至左第9位為1
- 關鍵代碼:bitMap[block] = bitMap[block] ^ (0x1 << (yuShu - 1)) // 設置標記位:在之前bitMap已有結果的基礎上,設置第block塊上的第 “(0x1 << (yuShu - 1))” bit位為1
示例結果展示:
四、擴展
練習一:文件中有40億個互不相同的QQ號碼,請設計算法對QQ號碼進行排序\color{blue}{排序}排序,內存限制1G。
很顯然,直接用bitmap,
標記這40億個QQ號碼的存在性,然后從小到大遍歷正整數,當bitmapFlag的值為1時,就輸出該值,輸出后的正整數序列就是排序后的結果。
請注意,這里必須限制40億個QQ號碼互不相同。通過bitmap記錄,客觀上就自動完成了排序功能。
練習二:文件中有40億個互不相同的QQ號碼,求這些QQ號碼的中位數\color{blue}{中位數}中位數,內存限制1G。
一些刷題經驗豐富的人,最開始想到的肯定是用堆或者文件切割,這明顯是犯了本本主義錯誤。直接用bitmap排序,當場搞定中位數。
練習三:文件中有40億個互不相同的QQ號碼,求這些QQ號碼的topK\color{blue}{topK}topK,內存限制1G。
很多人背誦過topK問題,信心滿滿,想到用小頂堆或者文件切割,這明顯又是犯了本本主義錯誤。直接用bitmap排序,當場搞定topK問題。
練習四:文件中有80億個QQ號碼,試判斷其中是否存在相同\color{blue}{相同}相同的QQ號碼,內存限制1G。
一些吸取了經驗教訓的人肯定說,直接bitmap啊。然而,又一次錯了。根據容斥原理可知:
因為QQ號碼的個數是43億左右(理論值2^32 - 1),所以80億個QQ號碼必然存在相同的QQ號碼。
五、總結:
- QQ號理論上的范圍為:10001 - 43億(232),其類型為 unsigned int
- 43億QQ號所占內存大小,經計算后大約占 512M (滿足小于1G的要求)
- 40億QQ號所占內存大小,經計算后大約占 477M (滿足小于1G的要求)
- bitMap實現方案 及 異或 ^ 等位運算
- 利用 bitMap 來處理海量數據問題,內存占用低,滿足要求且可以取得不錯的效果。包括:排序、中位數、topK、去重 等等…
總結
以上是生活随笔為你收集整理的利用bitmap处理海量数据问题:43亿QQ号所占内存大小为什么是512M?40亿个QQ号如何去重?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 强制删除WPS 遗留的qingnse64
- 下一篇: AVPlayer(二)AVAsset