題目:數組
40億 大整數,組成了一個大文件。
想找到其中的 上中位數該怎麼辦?
內存:10MB,怎麼辦?
內存:20K,怎麼辦?
內存:有限幾個字符,怎麼辦?
條件:按行讀取文件,讀取操做不佔用內存。
大數據
應該具有的能力:
2^k = ? 應該都可以熟記,達到反射性反應的程度。
字節數 對應計算機中的 容量(T, G, M, K)spa
內存只有 10MB 的狀況
接下來咱們來解題:
看到大數據容量限制的,首先想到的是從範圍入手。
1. 數據是 有符號? / 無符號?
2. 咱們知道一個 4字節的無符號整數 範圍爲:0~42億
那麼咱們能夠用一個 unsigned int 來表示一個數出現的次數
(一個數最多出現 40億 次,故可以表示,不會溢出)
3. 咱們來計算 10MB 內存能夠存幾個 unsigned int 的數。 => 250萬
所以咱們知道 10MB 內存足夠咱們在 250W 範圍內進行 精細的詞頻統計(每一個數出現幾回)
4. 0~42億 內總共有 1680個 250W 範圍的段。所以咱們將 42億 的範圍按照 250W 進行分段。([0, 250w), [250w,500w)...)
創建一個 1680 的數組,遍歷大文件一次,來統計每一個段中出現數的個數。
count[i] 就表示在第 i 段的 連續的250W 的範圍內,出現了多少個數。
好比:一個數字值爲10億,那麼它應該就在 count[400] 這個段中,那麼進行操做 count[400]++ 便可。
5. 對 count 進行累加,直到 sum >= 20億。這樣咱們就能肯定第 20億 個數是來自哪一個範圍的。
6. 釋放該數組,再次遍歷大文件,利用 10MB 的空間對該範圍內的數進行 精細的詞頻統計。這樣便可以找到中位數了。
因而可知,以上作法是借用了 桶排序 的思想。排序
總結:
1. 利用限制的範圍計算出咱們可以在多大的範圍內進行 精細的詞頻統計。
2. 利用 精細的範圍 對總體範圍進行劃分,創建一個粗略的統計數組。
3. 遍歷大文件,找出中位數粗略的範圍。
4. 對該粗略的範圍進行精細的統計。內存
內存只有 20K 的狀況:
咱們依然用上面的方法來分析:
20K 的內存能夠支持 5000範圍大小 的精細詞頻統計。
而後咱們用 40億 / 5000 => 發現該數值已經怨願你大於 5000 了,咱們根本沒法進行粗略範圍的統計。
因而,咱們不妨逆過來思考。
直接從 粗略的範圍 出發進行統計。將其分紅 5000 份。
咱們依然可以得知 中位數 是在哪一個部分。而後看該範圍可否被精細統計。
若不能一直循環下去。變量
內存只有 有限幾個字符 的狀況(好比就8個字節,兩個變量):
採用二分的方法。最多二分 32 次,即須要讀 32 次文件。
1. 首先對 0~42 億二分(注意是對整個範圍進行二分),用一個變量 k 記下當前的值是多少。
遍歷文件一邊遍,計算當前小於當前值得數據個數 n。
2. 若 n < 21億,該數在小半部分。若 n > 21億,該數在大部分。
以此循環下去。循環