題目如下:
只有2g記憶體的pc機,在乙個存有10g個整數的檔案,從中找到中位數,寫乙個演算法。
給出了四種方法來解決
演算法:1.利用外排序的方法,進行排序 ,然後再去找中位數
2.另外還有個思路利用堆
先求第1g大,然後利用該元素求第2g大,然後利用第2g大,求第3g大...當然這樣的話雖不需排序,但是磁碟操作會比較多,具體還需要分析下與外排序的效率哪個的磁碟io會比較多
建立乙個1g個整數的最大值堆,如果元素小於最大值則入堆,這樣可以得到第1g大的那個元素然後利用這個元素,重新建一次堆,這次入堆的條件還要加上大於這個第1g大的元素,這樣建完堆可以得到第2g大的那個...
3.借鑑基數排序思想
偶認為可以用位來判斷計數,從最高位到最低位,為了方便表述我們假設為無符號整數,即0x00000000~0xffffffff依次遞增,那麼可以遍歷所有資料,並記錄最高位為0和1的個數(最高位為0的肯定是小於最高位為1的)記為n0、n1
那麼根據n0和n1的大小就可以知道中位數的最高位是0還是1
假設n0>n1,那麼再計算n00和n01,
如果n00>(n01+n1),則說明中位數的最高兩位是00
再計算n000和n001.。。。依次計算就能找到中位數
如果改進一下,設定多個計數器
好像一次磁碟io也可以統計出n0,n00,....的數值
4.借鑑桶排序思想
乙個整數假設是32位無符號數
第一次掃瞄把0~2^32-1分成2^16個區間,記錄每個區間的整數數目
找出中位數具體所在區間65536*i~65536*(i+1)-1
第二次掃瞄則可找出具體中位數數值
第一次掃瞄已經找出中位數具體所在區間65536*i~65536*(i+1)-1
然後第二次掃瞄再統計在該區間內每個數出現的次數,就可以了
也有敘述
題目:在乙個檔案中有 10g 個整數,亂序排列,要求找出中位數。記憶體限制為 2g。只寫出思路即可(記憶體限制為 2g的意思就是,可以使用2g的空間來執行程式,而不考慮這台機器上的其他軟體的占用記憶體)。
分析:既然要找中位數,很簡單就是排序的想法。那麼基於位元組的桶排序是乙個可行的方法
:思想:將整形的每1byte作為乙個關鍵字,也就是說乙個整形可以拆成4個keys,而且最高位的keys越大,整數越大。如果高位keys相同,則比較次高位的keys。整個比較過程類似於字串的字典序。
第一步:把10g整數每2g讀入一次記憶體,然後一次遍歷這536,870,912個資料。每個資料用位運算">>"取出最高8位(31-24)。這8bits(0-255)最多表示255個桶,那麼可以根據8bit的值來確定丟入第幾個桶。最後把每個桶寫入乙個磁碟檔案中,同時在記憶體中統計每個桶內資料的數量,自然這個數量只需要255個整形空間即可。
代價:(1) 10g資料依次讀入記憶體的io代價(這個是無法避免的,cpu不能直接在磁碟上運算)。(2)在記憶體中遍歷536,870,912個資料,這是乙個o(n)的線性時間複雜度。(3)把255個桶寫會到255個磁碟檔案空間中,這個代價是額外的,也就是多付出一倍的10g資料轉移的時間。
第二步:根據記憶體中255個桶內的數量,計算中位數在第幾個桶中。很顯然,2,684,354,560個數中位數是第1,342,177,280個。假設前127個桶的資料量相加,發現少於1,342,177,280,把第128個桶資料量加上,大於1,342,177,280。說明,中位數必在磁碟的第128個桶中。而且在這個桶的第1,342,177,280-n(0-127)個數字上。n(0-127)表示前127個桶的資料量之和。然後把第128個檔案中的整數讀入記憶體。(平均而言,每個檔案的大小估計在10g/128=80m左右,當然也不一定,但是超過2g的可能性很小)。
代價:(1)迴圈計算255個桶中的資料量累加,需要o(m)的代價,其中m<255。(2)讀入乙個大概80m左右檔案大小的io代價。
注意,**的情況下,這個需要讀入的第128號檔案仍然大於2g,那麼整個讀入仍然可以按照第一步分批來進行讀取。
第三步:繼續以記憶體中的整數的次高8bit進行桶排序(23-16)。過程和第一步相同,也是255個桶。
第四步:一直下去,直到最低位元組(7-0bit)的桶排序結束。我相信這個時候完全可以在記憶體中使用一次快排就可以了。
整個過程的時間複雜度在o(n)的線性級別上(沒有任何迴圈巢狀)。但主要時間消耗在第一步的第二次記憶體-磁碟資料交換上,即10g資料分255個檔案寫回磁碟上。一般而言,如果第二步過後,記憶體可以容納下存在中位數的某乙個檔案的話,直接快排就可以了。關於快排的效率,可以看看我部落格中的資料。
海量資料求中位數
參考 1.最簡單 排序 2.堆 4g資料,1g記憶體 步驟 先將1g記憶體都塞進乙個大頂堆,然後小於堆頂的數,插入堆,並pop堆頂,一次遍歷後,得到第1g大的數 第二次遍歷,過濾小於第1g大的數,同樣塞滿乙個1g的大頂堆,小於堆頂的插入堆,並pop堆頂,得到第2g大的數字 3.二分 統計 比如數字範...
從海量資料中找中位數(c語言實現)
題目 5億個int,從中找出第k大的數 演算法 之後補上。實現 include include include include include include include include include typedef struct bucket t bucket t static unsign...
從海量資料中找出中位數
題目 在乙個檔案中有 10g 個整數,亂序排列,要求找出中位數。記憶體限制為 2g。只寫出思路即可 記憶體限制為 2g的意思就是,可以使用2g的空間來執行程式,而不考慮這台機器上的其他軟體的占用記憶體 關於中位數 資料排序後,位置在最中間的數值。即將資料分成兩部分,一部分大於該數值,一部分小於該數值...