99%的海量數(shù)據(jù)處理面試題

教你如何迅速秒殺掉:99%的海量數(shù)據(jù)處理面試題

本文經(jīng)過大量細(xì)致的優(yōu)化后臭胜,收錄于我的新書《編程之法》第六章中糙麦,新書目前已上架京東/當(dāng)當(dāng)/亞馬遜

作者:July

出處:結(jié)構(gòu)之法算法之道blog

前言

一般而言偎窘,標(biāo)題含有“秒殺”购公,“99%”蕴侣,“史上最全/最強(qiáng)”等詞匯的往往都脫不了嘩眾取寵之嫌,但進(jìn)一步來講数苫,如果讀者讀罷此文聪舒,卻無任何收獲,那么虐急,我也甘愿背負(fù)這樣的罪名 :-)箱残,同時,此文可以看做是對這篇文章:十道海量數(shù)據(jù)處理面試題與十個方法大總結(jié)的一般抽象性總結(jié)止吁。

畢竟受文章和理論之限被辑,本文將摒棄絕大部分的細(xì)節(jié),只談方法/模式論赏殃,且注重用最通俗最直白的語言闡述相關(guān)問題敷待。最后,有一點(diǎn)必須強(qiáng)調(diào)的是仁热,全文行文是基于面試題的分析基礎(chǔ)之上的榜揖,具體實踐過程中,還是得具體情況具體分析抗蠢,且各個場景下需要考慮的細(xì)節(jié)也遠(yuǎn)比本文所描述的任何一種解決方法復(fù)雜得多举哟。

OK,若有任何問題迅矛,歡迎隨時不吝賜教妨猩。謝謝。

何謂海量數(shù)據(jù)處理秽褒?

所謂海量數(shù)據(jù)處理壶硅,無非就是基于海量數(shù)據(jù)上的存儲、處理销斟、操作庐椒。何謂海量,就是數(shù)據(jù)量太大蚂踊,所以導(dǎo)致要么是無法在較短時間內(nèi)迅速解決约谈,要么是數(shù)據(jù)太大,導(dǎo)致無法一次性裝入內(nèi)存犁钟。

那解決辦法呢?針對時間棱诱,我們可以采用巧妙的算法搭配合適的數(shù)據(jù)結(jié)構(gòu),如Bloom filter/Hash/bit-map/堆/數(shù)據(jù)庫或倒排索引/trie樹涝动,針對空間迈勋,無非就一個辦法:大而化小,分而治之(hash映射)醋粟,你不是說規(guī)模太大嘛靡菇,那簡單啊担败,就把規(guī)模大化為規(guī)模小的,各個擊破不就完了嘛镰官。

至于所謂的單機(jī)及集群問題,通俗點(diǎn)來講吗货,單機(jī)就是處理裝載數(shù)據(jù)的機(jī)器有限(只要考慮cpu泳唠,內(nèi)存,硬盤的數(shù)據(jù)交互)宙搬,而集群笨腥,機(jī)器有多輛,適合分布式處理勇垛,并行計算(更多考慮節(jié)點(diǎn)和節(jié)點(diǎn)間的數(shù)據(jù)交互)脖母。

再者,通過本blog內(nèi)的有關(guān)海量數(shù)據(jù)處理的文章:Big Data Processing闲孤,我們已經(jīng)大致知道谆级,處理海量數(shù)據(jù)問題,無非就是:

分而治之/hash映射 + hash統(tǒng)計 + 堆/快速/歸并排序讼积;

雙層桶劃分

Bloom filter/Bitmap肥照;

Trie樹/數(shù)據(jù)庫/倒排索引;

外排序勤众;

分布式處理之Hadoop/Mapreduce舆绎。

下面,本文第一部分们颜、從set/map談到hashtable/hash_map/hash_set吕朵,簡要介紹下set/map/multiset/multimap,及hash_set/hash_map/hash_multiset/hash_multimap之區(qū)別(萬丈高樓平地起窥突,基礎(chǔ)最重要)努溃,而本文第二部分,則針對上述那6種方法模式結(jié)合對應(yīng)的海量數(shù)據(jù)處理面試題分別具體闡述波岛。

第一部分茅坛、從set/map談到hashtable/hash_map/hash_set

稍后本文第二部分中將多次提到hash_map/hash_set,下面稍稍介紹下這些容器则拷,以作為基礎(chǔ)準(zhǔn)備贡蓖。一般來說,STL容器分兩種煌茬,

序列式容器(vector/list/deque/stack/queue/heap)斥铺,

關(guān)聯(lián)式容器。關(guān)聯(lián)式容器又分為set(集合)和map(映射表)兩大類坛善,以及這兩大類的衍生體multiset(多鍵集合)和multimap(多鍵映射表)晾蜘,這些容器均以RB-tree完成邻眷。此外,還有第3類關(guān)聯(lián)式容器剔交,如hashtable(散列表)肆饶,以及以hashtable為底層機(jī)制完成的hash_set(散列集合)/hash_map(散列映射表)/hash_multiset(散列多鍵集合)/hash_multimap(散列多鍵映射表)。也就是說岖常,set/map/multiset/multimap都內(nèi)含一個RB-tree驯镊,而hash_set/hash_map/hash_multiset/hash_multimap都內(nèi)含一個hashtable。

所謂關(guān)聯(lián)式容器竭鞍,類似關(guān)聯(lián)式數(shù)據(jù)庫板惑,每筆數(shù)據(jù)或每個元素都有一個鍵值(key)和一個實值(value),即所謂的Key-Value(鍵-值對)偎快。當(dāng)元素被插入到關(guān)聯(lián)式容器中時冯乘,容器內(nèi)部結(jié)構(gòu)(RB-tree/hashtable)便依照其鍵值大小,以某種特定規(guī)則將這個元素放置于適當(dāng)位置晒夹。

包括在非關(guān)聯(lián)式數(shù)據(jù)庫中裆馒,比如,在MongoDB內(nèi)丐怯,文檔(document)是最基本的數(shù)據(jù)組織形式领追,每個文檔也是以Key-Value(鍵-值對)的方式組織起來。一個文檔可以有多個Key-Value組合响逢,每個Value可以是不同的類型绒窑,比如String、Integer舔亭、List等等些膨。

{ "name" : "July",

"sex" : "male",

"age" : 23 }

set/map/multiset/multimap

set,同map一樣钦铺,所有元素都會根據(jù)元素的鍵值自動被排序订雾,因為set/map兩者的所有各種操作汉柒,都只是轉(zhuǎn)而調(diào)用RB-tree的操作行為炬守,不過,值得注意的是分预,兩者都不允許兩個元素有相同的鍵值沼本。

不同的是:set的元素不像map那樣可以同時擁有實值(value)和鍵值(key)噩峦,set元素的鍵值就是實值,實值就是鍵值抽兆,而map的所有元素都是pair识补,同時擁有實值(value)和鍵值(key),pair的第一個元素被視為鍵值辫红,第二個元素被視為實值凭涂。

至于multiset/multimap祝辣,他們的特性及用法和set/map完全相同,唯一的差別就在于它們允許鍵值重復(fù)切油,即所有的插入操作基于RB-tree的insert_equal()而非insert_unique()蝙斜。

hash_set/hash_map/hash_multiset/hash_multimap

hash_set/hash_map,兩者的一切操作都是基于hashtable之上澎胡。不同的是乍炉,hash_set同set一樣,同時擁有實值和鍵值滤馍,且實質(zhì)就是鍵值,鍵值就是實值底循,而hash_map同map一樣巢株,每一個元素同時擁有一個實值(value)和一個鍵值(key),所以其使用方式熙涤,和上面的map基本相同阁苞。但由于hash_set/hash_map都是基于hashtable之上,所以不具備自動排序功能祠挫。為什么?因為hashtable沒有自動排序功能那槽。

至于hash_multiset/hash_multimap的特性與上面的multiset/multimap完全相同,唯一的差別就是它們hash_multiset/hash_multimap的底層實現(xiàn)機(jī)制是hashtable(而multiset/multimap等舔,上面說了骚灸,底層實現(xiàn)機(jī)制是RB-tree),所以它們的元素都不會被自動排序慌植,不過也都允許鍵值重復(fù)甚牲。

所以,綜上蝶柿,說白了丈钙,什么樣的結(jié)構(gòu)決定其什么樣的性質(zhì),因為set/map/multiset/multimap都是基于RB-tree之上交汤,所以有自動排序功能雏赦,而hash_set/hash_map/hash_multiset/hash_multimap都是基于hashtable之上,所以不含有自動排序功能芙扎,至于加個前綴multi_無非就是允許鍵值重復(fù)而已星岗。

此外,

關(guān)于什么hash戒洼,請看blog內(nèi)此篇文章伍茄;

關(guān)于紅黑樹,請參看blog內(nèi)系列文章施逾,

關(guān)于hash_map的具體應(yīng)用:請看這里敷矫,關(guān)于hash_set:請看此文例获。

OK,接下來曹仗,請看本文第二部分榨汤、處理海量數(shù)據(jù)問題之六把密匙。

第二部分怎茫、處理海量數(shù)據(jù)問題之六把密匙

密匙一收壕、分而治之/Hash映射 + Hash_map統(tǒng)計 + 堆/快速/歸并排序

1、海量日志數(shù)據(jù)轨蛤,提取出某日訪問百度次數(shù)最多的那個IP蜜宪。

既然是海量數(shù)據(jù)處理,那么可想而知祥山,給我們的數(shù)據(jù)那就一定是海量的圃验。針對這個數(shù)據(jù)的海量,我們?nèi)绾沃帜?對的缝呕,無非就是分而治之/hash映射 + hash統(tǒng)計 + 堆/快速/歸并排序澳窑,說白了,就是先映射供常,而后統(tǒng)計摊聋,最后排序:

分而治之/hash映射:針對數(shù)據(jù)太大,內(nèi)存受限栈暇,只能是:把大文件化成(取模映射)小文件麻裁,即16字方針:大而化小,各個擊破源祈,縮小規(guī)模悲立,逐個解決

hash_map統(tǒng)計:當(dāng)大文件轉(zhuǎn)化了小文件,那么我們便可以采用常規(guī)的hash_map(ip新博,value)來進(jìn)行頻率統(tǒng)計薪夕。

堆/快速排序:統(tǒng)計完了之后,便進(jìn)行排序(可采取堆排序)赫悄,得到次數(shù)最多的IP原献。

具體而論,則是: “首先是這一天埂淮,并且是訪問百度的日志中的IP取出來姑隅,逐個寫入到一個大文件中。注意到IP是32位的倔撞,最多有個2^32個IP讲仰。同樣可以采用映射的方法,比如%1000痪蝇,把整個大文件映射為1000個小文件鄙陡,再找出每個小文中出現(xiàn)頻率最大的IP(可以采用hash_map對那1000個文件中的所有IP進(jìn)行頻率統(tǒng)計冕房,然后依次找出各個文件中頻率最大的那個IP)及相應(yīng)的頻率。然后再在這1000個最大的IP中趁矾,找出那個頻率最大的IP耙册,即為所求『恋罚”--十道海量數(shù)據(jù)處理面試題與十個方法大總結(jié)详拙。

關(guān)于本題,還有幾個問題蔓同,如下:

1饶辙、Hash取模是一種等價映射,不會存在同一個元素分散到不同小文件中的情況斑粱,即這里采用的是mod1000算法弃揽,那么相同的IP在hash取模后,只可能落在同一個文件中珊佣,不可能被分散的。因為如果兩個IP相等披粟,那么經(jīng)過Hash(IP)之后的哈希值是相同的咒锻,將此哈希值取模(如模1000),必定仍然相等守屉。

2惑艇、那到底什么是hash映射呢?簡單來說拇泛,就是為了便于計算機(jī)在有限的內(nèi)存中處理big數(shù)據(jù)滨巴,從而通過一種映射散列的方式讓數(shù)據(jù)均勻分布在對應(yīng)的內(nèi)存位置(如大數(shù)據(jù)通過取余的方式映射成小樹存放在內(nèi)存中,或大文件映射成多個小文件)俺叭,而這個映射散列方式便是我們通常所說的hash函數(shù)恭取,設(shè)計的好的hash函數(shù)能讓數(shù)據(jù)均勻分布而減少沖突。盡管數(shù)據(jù)映射到了另外一些不同的位置熄守,但數(shù)據(jù)還是原來的數(shù)據(jù)蜈垮,只是代替和表示這些原始數(shù)據(jù)的形式發(fā)生了變化而已。

OK裕照,有興趣的攒发,還可以再了解下一致性hash算法,見blog內(nèi)此文第五部分:http://blog.csdn.net/v_july_v/article/details/6879101晋南。

2惠猿、尋找熱門查詢,300萬個查詢字符串中統(tǒng)計最熱門的10個查詢

原題:搜索引擎會通過日志文件把用戶每次檢索使用的所有檢索串都記錄下來负间,每個查詢串的長度為1-255字節(jié)偶妖。假設(shè)目前有一千萬個記錄(這些查詢串的重復(fù)度比較高姜凄,雖然總數(shù)是1千萬,但如果除去重復(fù)后餐屎,不超過3百萬個檀葛。一個查詢串的重復(fù)度越高,說明查詢它的用戶越多腹缩,也就是越熱門)屿聋,請你統(tǒng)計最熱門的10個查詢串,要求使用的內(nèi)存不能超過1G藏鹊。

解答:由上面第1題润讥,我們知道,數(shù)據(jù)大則劃為小的盘寡,如如一億個Ip求Top 10楚殿,可先%1000將ip分到1000個小文件中去,并保證一種ip只出現(xiàn)在一個文件中竿痰,再對每個小文件中的ip進(jìn)行hashmap計數(shù)統(tǒng)計并按數(shù)量排序脆粥,最后歸并或者最小堆依次處理每個小文件的top10以得到最后的結(jié)。

但如果數(shù)據(jù)規(guī)模比較小影涉,能一次性裝入內(nèi)存呢?比如這第2題变隔,雖然有一千萬個Query,但是由于重復(fù)度比較高蟹倾,因此事實上只有300萬的Query匣缘,每個Query255Byte,因此我們可以考慮把他們都放進(jìn)內(nèi)存中去(300萬個字符串假設(shè)沒有重復(fù)鲜棠,都是最大長度肌厨,那么最多占用內(nèi)存3M*1K/4=0.75G。所以可以將所有字符串都存放在內(nèi)存中進(jìn)行處理)豁陆,而現(xiàn)在只是需要一個合適的數(shù)據(jù)結(jié)構(gòu)柑爸,在這里,HashTable絕對是我們優(yōu)先的選擇盒音。

所以我們放棄分而治之/hash映射的步驟竖配,直接上hash統(tǒng)計,然后排序里逆。So进胯,針對此類典型的TOP K問題,采取的對策往往是:hashmap + 堆原押。如下所示:

hash_map統(tǒng)計:先對這批海量數(shù)據(jù)預(yù)處理胁镐。具體方法是:維護(hù)一個Key為Query字串,Value為該Query出現(xiàn)次數(shù)的HashTable,即hash_map(Query盯漂,Value)颇玷,每次讀取一個Query,如果該字串不在Table中就缆,那么加入該字串帖渠,并且將Value值設(shè)為1;如果該字串在Table中竭宰,那么將該字串的計數(shù)加一即可空郊。最終我們在O(N)的時間復(fù)雜度內(nèi)用Hash表完成了統(tǒng)計;

堆排序:第二步切揭、借助堆這個數(shù)據(jù)結(jié)構(gòu)狞甚,找出Top K,時間復(fù)雜度為N‘logK廓旬。即借助堆結(jié)構(gòu)哼审,我們可以在log量級的時間內(nèi)查找和調(diào)整/移動。因此孕豹,維護(hù)一個K(該題目中是10)大小的小根堆涩盾,然后遍歷300萬的Query,分別和根元素進(jìn)行對比励背。所以春霍,我們最終的時間復(fù)雜度是:O(N) + N' * O(logK),(N為1000萬椅野,N’為300萬)终畅。

別忘了這篇文章中所述的堆排序思路:“維護(hù)k個元素的最小堆籍胯,即用容量為k的最小堆存儲最先遍歷到的k個數(shù)竟闪,并假設(shè)它們即是最大的k個數(shù),建堆費(fèi)時O(k)杖狼,并調(diào)整堆(費(fèi)時O(logk))后炼蛤,有k1>k2>...kmin(kmin設(shè)為小頂堆中最小元素)。繼續(xù)遍歷數(shù)列蝶涩,每次遍歷一個元素x理朋,與堆頂元素比較,若x>kmin绿聘,則更新堆(x入堆嗽上,用時logk),否則不更新堆熄攘。這樣下來兽愤,總費(fèi)時O(k*logk+(n-k)*logk)=O(n*logk)。此方法得益于在堆中,查找等各項操作時間復(fù)雜度均為logk浅萧≈鹕常”--第三章續(xù)、Top K算法問題的實現(xiàn)洼畅。

當(dāng)然吩案,你也可以采用trie樹,關(guān)鍵字域存該查詢串出現(xiàn)的次數(shù)帝簇,沒有出現(xiàn)為0徘郭。最后用10個元素的最小推來對出現(xiàn)頻率進(jìn)行排序。

3己儒、有一個1G大小的一個文件崎岂,里面每一行是一個詞,詞的大小不超過16字節(jié)闪湾,內(nèi)存限制大小是1M冲甘。返回頻數(shù)最高的100個詞。

由上面那兩個例題途样,分而治之 + hash統(tǒng)計 + 堆/快速排序這個套路江醇,我們已經(jīng)開始有了屢試不爽的感覺。下面何暇,再拿幾道再多多驗證下陶夜。請看此第3題:又是文件很大,又是內(nèi)存受限裆站,咋辦?還能怎么辦呢?無非還是:

分而治之/hash映射:順序讀文件中条辟,對于每個詞x,取hash(x)%5000宏胯,然后按照該值存到5000個小文件(記為x0,x1,...x4999)中羽嫡。這樣每個文件大概是200k左右。如果其中的有的文件超過了1M大小肩袍,還可以按照類似的方法繼續(xù)往下分杭棵,直到分解得到的小文件的大小都不超過1M。

hash_map統(tǒng)計:對每個小文件氛赐,采用trie樹/hash_map等統(tǒng)計每個文件中出現(xiàn)的詞以及相應(yīng)的頻率魂爪。

堆/歸并排序:取出出現(xiàn)頻率最大的100個詞(可以用含100個結(jié)點(diǎn)的最小堆)后,再把100個詞及相應(yīng)的頻率存入文件艰管,這樣又得到了5000個文件滓侍。最后就是把這5000個文件進(jìn)行歸并(類似于歸并排序)的過程了。

4牲芋、海量數(shù)據(jù)分布在100臺電腦中撩笆,想個辦法高效統(tǒng)計出這批數(shù)據(jù)的TOP10尔破。

如果每個數(shù)據(jù)元素只出現(xiàn)一次,而且只出現(xiàn)在某一臺機(jī)器中浇衬,那么可以采取以下步驟統(tǒng)計出現(xiàn)次數(shù)TOP10的數(shù)據(jù)元素:

堆排序:在每臺電腦上求出TOP10懒构,可以采用包含10個元素的堆完成(TOP10小,用最大堆耘擂,TOP10大胆剧,用最小堆,比如求TOP10大醉冤,我們首先取前10個元素調(diào)整成最小堆秩霍,如果發(fā)現(xiàn),然后掃描后面的數(shù)據(jù)蚁阳,并與堆頂元素比較铃绒,如果比堆頂元素大,那么用該元素替換堆頂螺捐,然后再調(diào)整為最小堆颠悬。最后堆中的元素就是TOP10大)。

求出每臺電腦上的TOP10后定血,然后把這100臺電腦上的TOP10組合起來赔癌,共1000個數(shù)據(jù),再利用上面類似的方法求出TOP10就可以了澜沟。

但如果同一個元素重復(fù)出現(xiàn)在不同的電腦中呢灾票,如下例子所述:

這個時候,你可以有兩種方法:

遍歷一遍所有數(shù)據(jù)茫虽,重新hash取摸刊苍,如此使得同一個元素只出現(xiàn)在單獨(dú)的一臺電腦中,然后采用上面所說的方法濒析,統(tǒng)計每臺電腦中各個元素的出現(xiàn)次數(shù)找出TOP10正什,繼而組合100臺電腦上的TOP10,找出最終的TOP10悼枢。

或者埠忘,暴力求解:直接統(tǒng)計統(tǒng)計每臺電腦中各個元素的出現(xiàn)次數(shù)脾拆,然后把同一個元素在不同機(jī)器中的出現(xiàn)次數(shù)相加馒索,最終從所有數(shù)據(jù)中找出TOP10。

5名船、有10個文件绰上,每個文件1G,每個文件的每一行存放的都是用戶的query渠驼,每個文件的query都可能重復(fù)蜈块。要求你按照query的頻度排序。

方案1:直接上:

hash映射:順序讀取10個文件,按照hash(query)%10的結(jié)果將query寫入到另外10個文件(記為a0,a1,..a9)中百揭。這樣新生成的文件每個的大小大約也1G(假設(shè)hash函數(shù)是隨機(jī)的)爽哎。

hash_map統(tǒng)計:找一臺內(nèi)存在2G左右的機(jī)器,依次對用hash_map(query, query_count)來統(tǒng)計每個query出現(xiàn)的次數(shù)器一。注:hash_map(query,query_count)是用來統(tǒng)計每個query的出現(xiàn)次數(shù)课锌,不是存儲他們的值,出現(xiàn)一次祈秕,則count+1渺贤。

堆/快速/歸并排序:利用快速/堆/歸并排序按照出現(xiàn)次數(shù)進(jìn)行排序,將排序好的query和對應(yīng)的query_cout輸出到文件中请毛,這樣得到了10個排好序的文件(記為

)志鞍。最后,對這10個文件進(jìn)行歸并排序(內(nèi)排序與外排序相結(jié)合)方仿。根據(jù)此方案1固棚,這里有一份實現(xiàn):https://github.com/ooooola/sortquery/blob/master/querysort.py

除此之外仙蚜,此題還有以下兩個方法:

方案2:一般query的總量是有限的玻孟,只是重復(fù)的次數(shù)比較多而已,可能對于所有的query鳍征,一次性就可以加入到內(nèi)存了黍翎。這樣,我們就可以采用trie樹/hash_map等直接來統(tǒng)計每個query出現(xiàn)的次數(shù)艳丛,然后按出現(xiàn)次數(shù)做快速/堆/歸并排序就可以了匣掸。

方案3:與方案1類似,但在做完hash氮双,分成多個文件后碰酝,可以交給多個文件來處理,采用分布式的架構(gòu)來處理(比如MapReduce)戴差,最后再進(jìn)行合并送爸。

6、 給定a暖释、b兩個文件袭厂,各存放50億個url,每個url各占64字節(jié)球匕,內(nèi)存限制是4G纹磺,讓你找出a、b文件共同的url亮曹?

可以估計每個文件安的大小為5G×64=320G橄杨,遠(yuǎn)遠(yuǎn)大于內(nèi)存限制的4G秘症。所以不可能將其完全加載到內(nèi)存中處理∈浇茫考慮采取分而治之的方法乡摹。

分而治之/hash映射:遍歷文件a,對每個url求取

采转,然后根據(jù)所取得的值將url分別存儲到1000個小文件(記為

趟卸,這里漏寫個了a1)中。這樣每個小文件的大約為300M氏义。遍歷文件b锄列,采取和a相同的方式將url分別存儲到1000小文件中(記為

)。這樣處理后惯悠,所有可能相同的url都在對應(yīng)的小文件(

)中邻邮,不對應(yīng)的小文件不可能有相同的url。然后我們只要求出1000對小文件中相同的url即可克婶。

hash_set統(tǒng)計:求每對小文件中相同的url時筒严,可以把其中一個小文件的url存儲到hash_set中。然后遍歷另一個小文件的每個url情萤,看其是否在剛才構(gòu)建的hash_set中鸭蛙,如果是,那么就是共同的url筋岛,存到文件里面就可以了娶视。

OK,此第一種方法:分而治之/hash映射 + hash統(tǒng)計 + 堆/快速/歸并排序睁宰,再看最后4道題肪获,如下:

7、怎么在海量數(shù)據(jù)中找出重復(fù)次數(shù)最多的一個柒傻?

方案:先做hash孝赫,然后求模映射為小文件,求出每個小文件中重復(fù)次數(shù)最多的一個红符,并記錄重復(fù)次數(shù)青柄。然后找出上一步求出的數(shù)據(jù)中重復(fù)次數(shù)最多的一個就是所求(具體參考前面的題)。

8预侯、上千萬或上億數(shù)據(jù)(有重復(fù))致开,統(tǒng)計其中出現(xiàn)次數(shù)最多的前N個數(shù)據(jù)。

方案:上千萬或上億的數(shù)據(jù)雌桑,現(xiàn)在的機(jī)器的內(nèi)存應(yīng)該能存下喇喉。所以考慮采用hash_map/搜索二叉樹/紅黑樹等來進(jìn)行統(tǒng)計次數(shù)祖今。然后利用堆取出前N個出現(xiàn)次數(shù)最多的數(shù)據(jù)校坑。

9拣技、一個文本文件,大約有一萬行耍目,每行一個詞膏斤,要求統(tǒng)計出其中最頻繁出現(xiàn)的前10個詞,請給出思想邪驮,給出時間復(fù)雜度分析莫辨。

方案1:如果文件比較大,無法一次性讀入內(nèi)存毅访,可以采用hash取模的方法沮榜,將大文件分解為多個小文件,對于單個小文件利用hash_map統(tǒng)計出每個小文件中10個最常出現(xiàn)的詞喻粹,然后再進(jìn)行歸并處理蟆融,找出最終的10個最常出現(xiàn)的詞。

方案2:通過hash取模將大文件分解為多個小文件后守呜,除了可以用hash_map統(tǒng)計出每個小文件中10個最常出現(xiàn)的詞型酥,也可以用trie樹統(tǒng)計每個詞出現(xiàn)的次數(shù),時間復(fù)雜度是O(n*le)(le表示單詞的平準(zhǔn)長度)查乒,最終同樣找出出現(xiàn)最頻繁的前10個詞(可用堆來實現(xiàn))弥喉,時間復(fù)雜度是O(n*lg10)。

10. 1000萬字符串玛迄,其中有些是重復(fù)的由境,需要把重復(fù)的全部去掉,保留沒有重復(fù)的字符串蓖议。請怎么設(shè)計和實現(xiàn)藻肄?

方案1:這題用trie樹比較合適,hash_map也行拒担。

方案2:from xjbzju:嘹屯,1000w的數(shù)據(jù)規(guī)模插入操作完全不現(xiàn)實,以前試過在stl下100w元素插入set中已經(jīng)慢得不能忍受从撼,覺得基于hash的實現(xiàn)不會比紅黑樹好太多州弟,使用vector+sort+unique都要可行許多,建議還是先hash成小文件分開處理再綜合低零。

上述方案2中讀者xbzju的方法讓我想到了一些問題婆翔,即是set/map,與hash_set/hash_map的性能比較?共計3個問題,如下:

1彤蔽、hash_set在千萬級數(shù)據(jù)下扯旷,insert操作優(yōu)于set? 這位blog:http://t.cn/zOibP7t給的實踐數(shù)據(jù)可靠不?

2、那map和hash_map的性能比較呢? 誰做過相關(guān)實驗?

3最蕾、那查詢操作呢依溯,如下段文字所述?

或者小數(shù)據(jù)量時用map,構(gòu)造快瘟则,大數(shù)據(jù)量時用hash_map?

rbtree PK hashtable

據(jù)朋友№邦卡貓№的做的紅黑樹和hash table的性能測試中發(fā)現(xiàn):當(dāng)數(shù)據(jù)量基本上int型key時黎炉,hash?table是rbtree的3-4倍,但hash?table一般會浪費(fèi)大概一半內(nèi)存醋拧。

因為hash?table所做的運(yùn)算就是個%慷嗜,而rbtree要比較很多,比如rbtree要看value的數(shù)據(jù) 丹壕,每個節(jié)點(diǎn)要多出3個指針(或者偏移量) 如果需要其他功能庆械,比如,統(tǒng)計某個范圍內(nèi)的key的數(shù)量菌赖,就需要加一個計數(shù)成員干奢。

且1s?rbtree能進(jìn)行大概50w+次插入,hash?table大概是差不多200w次盏袄。不過很多的時候忿峻,其速度可以忍了,例如倒排索引差不多也是這個速度辕羽,而且單線程逛尚,且倒排表的拉鏈長度不會太大。正因為基于樹的實現(xiàn)其實不比hashtable慢到哪里去刁愿,所以數(shù)據(jù)庫的索引一般都是用的B/B+樹绰寞,而且B+樹還對磁盤友好(B樹能有效降低它的高度,所以減少磁盤交互次數(shù))铣口。比如現(xiàn)在非常流行的NoSQL數(shù)據(jù)庫滤钱,像MongoDB也是采用的B樹索引。關(guān)于B樹系列脑题,請參考本blog內(nèi)此篇文章:從B樹件缸、B+樹、B*樹談到R 樹叔遂。更多請待后續(xù)實驗論證他炊。

11. 一個文本文件,找出前10個經(jīng)常出現(xiàn)的詞已艰,但這次文件比較長痊末,說是上億行或十億行,總之無法一次讀入內(nèi)存哩掺,問最優(yōu)解凿叠。

方案1:首先根據(jù)用hash并求模,將文件分解為多個小文件,對于單個文件利用上題的方法求出每個文件件中10個最常出現(xiàn)的詞盒件。然后再進(jìn)行歸并處理蹬碧,找出最終的10個最常出現(xiàn)的詞。

12. 100w個數(shù)中找出最大的100個數(shù)履恩。

方案1:采用局部淘汰法锰茉。選取前100個元素呢蔫,并排序切心,記為序列L。然后一次掃描剩余的元素x片吊,與排好序的100個元素中最小的元素比绽昏,如果比這個最小的要大,那么把這個最小的元素刪除俏脊,并把x利用插入排序的思想全谤,插入到序列L中。依次循環(huán)爷贫,知道掃描了所有的元素认然。復(fù)雜度為O(100w*100)。

方案2:采用快速排序的思想漫萄,每次分割之后只考慮比軸大的一部分卷员,知道比軸大的一部分在比100多的時候,采用傳統(tǒng)排序算法排序腾务,取前100個毕骡。復(fù)雜度為O(100w*100)。

方案3:在前面的題中岩瘦,我們已經(jīng)提到了未巫,用一個含100個元素的最小堆完成。復(fù)雜度為O(100w*lg100)启昧。

接下來叙凡,咱們來看第二種方法,雙層捅劃分密末。

密匙二狭姨、多層劃分

多層劃分----其實本質(zhì)上還是分而治之的思想,重在“分”的技巧上苏遥!

適用范圍:第k大饼拍,中位數(shù),不重復(fù)或重復(fù)的數(shù)字

基本原理及要點(diǎn):因為元素范圍很大田炭,不能利用直接尋址表师抄,所以通過多次劃分,逐步確定范圍教硫,然后最后在一個可以接受的范圍內(nèi)進(jìn)行叨吮。

問題實例:

13辆布、2.5億個整數(shù)中找出不重復(fù)的整數(shù)的個數(shù),內(nèi)存空間不足以容納這2.5億個整數(shù)茶鉴。

有點(diǎn)像鴿巢原理锋玲,整數(shù)個數(shù)為2^32,也就是,我們可以將這2^32個數(shù)涵叮,劃分為2^8個區(qū)域(比如用單個文件代表一個區(qū)域)惭蹂,然后將數(shù)據(jù)分離到不同的區(qū)域,然后不同的區(qū)域在利用bitmap就可以直接解決了割粮。也就是說只要有足夠的磁盤空間盾碗,就可以很方便的解決。

14舀瓢、5億個int找它們的中位數(shù)廷雅。

思路一:這個例子比上面那個更明顯。首先我們將int劃分為2^16個區(qū)域京髓,然后讀取數(shù)據(jù)統(tǒng)計落到各個區(qū)域里的數(shù)的個數(shù)航缀,之后我們根據(jù)統(tǒng)計結(jié)果就可以判斷中位數(shù)落到那個區(qū)域,同時知道這個區(qū)域中的第幾大數(shù)剛好是中位數(shù)堰怨。然后第二次掃描我們只統(tǒng)計落在這個區(qū)域中的那些數(shù)就可以了芥玉。

實際上,如果不是int是int64诚些,我們可以經(jīng)過3次這樣的劃分即可降低到可以接受的程度飞傀。即可以先將int64分成2^24個區(qū)域,然后確定區(qū)域的第幾大數(shù)诬烹,在將該區(qū)域分成2^20個子區(qū)域砸烦,然后確定是子區(qū)域的第幾大數(shù),然后子區(qū)域里的數(shù)的個數(shù)只有2^20绞吁,就可以直接利用direct addr table進(jìn)行統(tǒng)計了幢痘。

思路二@綠色夾克衫:同樣需要做兩遍統(tǒng)計,如果數(shù)據(jù)存在硬盤上家破,就需要讀取2次颜说。

方法同基數(shù)排序有些像,開一個大小為65536的Int數(shù)組汰聋,第一遍讀取门粪,統(tǒng)計Int32的高16位的情況,也就是0-65535烹困,都算作0,65536 - 131071都算作1玄妈。就相當(dāng)于用該數(shù)除以65536。Int32 除以 65536的結(jié)果不會超過65536種情況,因此開一個長度為65536的數(shù)組計數(shù)就可以拟蜻。每讀取一個數(shù)绎签,數(shù)組中對應(yīng)的計數(shù)+1,考慮有負(fù)數(shù)的情況酝锅,需要將結(jié)果加32768后诡必,記錄在相應(yīng)的數(shù)組內(nèi)。

第一遍統(tǒng)計之后搔扁,遍歷數(shù)組爸舒,逐個累加統(tǒng)計,看中位數(shù)處于哪個區(qū)間阁谆,比如處于區(qū)間k碳抄,那么0- k-1的區(qū)間里數(shù)字的數(shù)量sum應(yīng)該

密匙三:Bloom filter/Bitmap

Bloom filter

關(guān)于什么是Bloom filter愉老,請參看blog內(nèi)此文:

海量數(shù)據(jù)處理之Bloom Filter詳解

適用范圍:可以用來實現(xiàn)數(shù)據(jù)字典场绿,進(jìn)行數(shù)據(jù)的判重,或者集合求交集

基本原理及要點(diǎn):

對于原理來說很簡單嫉入,位數(shù)組+k個獨(dú)立hash函數(shù)焰盗。將hash函數(shù)對應(yīng)的值的位數(shù)組置1,查找時如果發(fā)現(xiàn)所有hash函數(shù)對應(yīng)位都是1說明存在咒林,很明顯這個過程并不保證查找的結(jié)果是100%正確的熬拒。同時也不支持刪除一個已經(jīng)插入的關(guān)鍵字,因為該關(guān)鍵字對應(yīng)的位會牽動到其他的關(guān)鍵字垫竞。所以一個簡單的改進(jìn)就是 counting Bloom filter澎粟,用一個counter數(shù)組代替位數(shù)組,就可以支持刪除了欢瞪。

還有一個比較重要的問題活烙,如何根據(jù)輸入元素個數(shù)n,確定位數(shù)組m的大小及hash函數(shù)個數(shù)遣鼓。當(dāng)hash函數(shù)個數(shù)k=(ln2)*(m/n)時錯誤率最小啸盏。在錯誤率不大于E的情況下,m至少要等于n*lg(1/E)才能表示任意n個元素的集合骑祟。但m還應(yīng)該更大些回懦,因為還要保證bit數(shù)組里至少一半為0,則m應(yīng)該>=nlg(1/E)*lge 大概就是nlg(1/E)1.44倍(lg表示以2為底的對數(shù))次企。

舉個例子我們假設(shè)錯誤率為0.01怯晕,則此時m應(yīng)大概是n的13倍。這樣k大概是8個缸棵。

注意這里m與n的單位不同舟茶,m是bit為單位,而n則是以元素個數(shù)為單位(準(zhǔn)確的說是不同元素的個數(shù))。通常單個元素的長度都是有很多bit的稚晚。所以使用bloom filter內(nèi)存上通常都是節(jié)省的崇堵。

擴(kuò)展:

Bloom filter將集合中的元素映射到位數(shù)組中,用k(k為哈希函數(shù)個數(shù))個映射位是否全1表示元素在不在這個集合中客燕。Counting bloom filter(CBF)將位數(shù)組中的每一位擴(kuò)展為一個counter鸳劳,從而支持了元素的刪除操作。Spectral Bloom Filter(SBF)將其與集合元素的出現(xiàn)次數(shù)關(guān)聯(lián)也搓。SBF采用counter中的最小值來近似表示元素的出現(xiàn)頻率赏廓。

可以看下上文中的第6題:

“6、給你A,B兩個文件傍妒,各存放50億條URL幔摸,每條URL占用64字節(jié),內(nèi)存限制是4G颤练,讓你找出A,B文件共同的URL既忆。如果是三個乃至n個文件呢?

根據(jù)這個問題我們來計算下內(nèi)存的占用嗦玖,4G=2^32大概是40億*8大概是340億患雇,n=50億,如果按出錯率0.01算需要的大概是650億個bit∮畲欤現(xiàn)在可用的是340億苛吱,相差并不多,這樣可能會使出錯率上升些器瘪。另外如果這些urlip是一一對應(yīng)的翠储,就可以轉(zhuǎn)換成ip,則大大簡單了橡疼。

同時援所,上文的第5題:給定a、b兩個文件衰齐,各存放50億個url任斋,每個url各占64字節(jié),內(nèi)存限制是4G耻涛,讓你找出a废酷、b文件共同的url?如果允許有一定的錯誤率抹缕,可以使用Bloom filter澈蟆,4G內(nèi)存大概可以表示340億bit。將其中一個文件中的url使用Bloom filter映射為這340億bit卓研,然后挨個讀取另外一個文件的url趴俘,檢查是否與Bloom filter睹簇,如果是,那么該url應(yīng)該是共同的url(注意會有一定的錯誤率)寥闪√荩”

Bitmap

關(guān)于什么是Bitmap,請看blog內(nèi)此文第二部分:http://blog.csdn.net/v_july_v/article/details/6685962疲憋。

下面關(guān)于Bitmap的應(yīng)用凿渊,可以看下上文中的第13題,以及另外一道新題:

“13缚柳、在2.5億個整數(shù)中找出不重復(fù)的整數(shù)埃脏,注,內(nèi)存不足以容納這2.5億個整數(shù)秋忙。

方案1:采用2-Bitmap(每個數(shù)分配2bit彩掐,00表示不存在,01表示出現(xiàn)一次灰追,10表示多次堵幽,11無意義)進(jìn)行,共需內(nèi)存2^32 * 2 bit=1 GB內(nèi)存监嗜,還可以接受谐檀。然后掃描這2.5億個整數(shù)抡谐,查看Bitmap中相對應(yīng)位裁奇,如果是00變01,01變10麦撵,10保持不變刽肠。所描完事后,查看bitmap免胃,把對應(yīng)位是01的整數(shù)輸出即可音五。

方案2:也可采用與第1題類似的方法,進(jìn)行劃分小文件的方法羔沙。然后在小文件中找出不重復(fù)的整數(shù)躺涝,并排序。然后再進(jìn)行歸并扼雏,注意去除重復(fù)的元素坚嗜。

15、給40億個不重復(fù)的unsigned int的整數(shù)诗充,沒排過序的苍蔬,然后再給一個數(shù),如何快速判斷這個數(shù)是否在那40億個數(shù)當(dāng)中蝴蜓?

方案1:frome oo碟绑,用位圖/Bitmap的方法俺猿,申請512M的內(nèi)存,一個bit位代表一個unsigned int值格仲。讀入40億個數(shù)押袍,設(shè)置相應(yīng)的bit位,讀入要查詢的數(shù)凯肋,查看相應(yīng)bit位是否為1伯病,為1表示存在,為0表示不存在否过。

密匙四午笛、Trie樹/數(shù)據(jù)庫/倒排索引

Trie樹

適用范圍:數(shù)據(jù)量大,重復(fù)多苗桂,但是數(shù)據(jù)種類小可以放入內(nèi)存

基本原理及要點(diǎn):實現(xiàn)方式药磺,節(jié)點(diǎn)孩子的表示方式

擴(kuò)展:壓縮實現(xiàn)。

問題實例:

上面的第2題:尋找熱門查詢:查詢串的重復(fù)度比較高煤伟,雖然總數(shù)是1千萬癌佩,但如果除去重復(fù)后,不超過3百萬個便锨,每個不超過255字節(jié)围辙。

上面的第5題:有10個文件,每個文件1G放案,每個文件的每一行都存放的是用戶的query姚建,每個文件的query都可能重復(fù)。要你按照query的頻度排序吱殉。

1000萬字符串掸冤,其中有些是相同的(重復(fù)),需要把重復(fù)的全部去掉,保留沒有重復(fù)的字符串友雳。請問怎么設(shè)計和實現(xiàn)稿湿?

上面的第8題:一個文本文件,大約有一萬行押赊,每行一個詞饺藤,要求統(tǒng)計出其中最頻繁出現(xiàn)的前10個詞。其解決方法是:用trie樹統(tǒng)計每個詞出現(xiàn)的次數(shù)流礁,時間復(fù)雜度是O(n*le)(le表示單詞的平準(zhǔn)長度)涕俗,然后是找出出現(xiàn)最頻繁的前10個詞。

更多有關(guān)Trie樹的介紹崇棠,請參見此文:從Trie樹(字典樹)談到后綴樹咽袜。

數(shù)據(jù)庫索引

適用范圍:大數(shù)據(jù)量的增刪改查

基本原理及要點(diǎn):利用數(shù)據(jù)的設(shè)計實現(xiàn)方法,對海量數(shù)據(jù)的增刪改查進(jìn)行處理枕稀。

關(guān)于數(shù)據(jù)庫索引及其優(yōu)化询刹,更多可參見此文:http://www.cnblogs.com/pkuoliver/archive/2011/08/17/mass-data-topic-7-index-and-optimize.html谜嫉;

關(guān)于MySQL索引背后的數(shù)據(jù)結(jié)構(gòu)及算法原理,這里還有一篇很好的文章:http://blog.codinglabs.org/articles/theory-of-mysql-index.html凹联;

關(guān)于B 樹沐兰、B+ 樹、B* 樹及R 樹蔽挠,本blog內(nèi)有篇絕佳文章:http://blog.csdn.net/v_JULY_v/article/details/6530142住闯。

倒排索引(Inverted index)

適用范圍:搜索引擎,關(guān)鍵字查詢

基本原理及要點(diǎn):為何叫倒排索引澳淑?一種索引方法比原,被用來存儲在全文搜索下某個單詞在一個文檔或者一組文檔中的存儲位置的映射。

以英文為例杠巡,下面是要被索引的文本:

T0 = "it is what it is"

T1 = "what is it"

T2 = "it is a banana"

我們就能得到下面的反向文件索引:

"a": ? ? ?{2}

"banana": {2}

"is": ? ? {0, 1, 2}

"it": ? ? {0, 1, 2}

"what": ? {0, 1}

檢索的條件"what","is"和"it"將對應(yīng)集合的交集量窘。

正向索引開發(fā)出來用來存儲每個文檔的單詞的列表。正向索引的查詢往往滿足每個文檔有序頻繁的全文查詢和每個單詞在校驗文檔中的驗證這樣的查詢氢拥。在正向索引中蚌铜,文檔占據(jù)了中心的位置,每個文檔指向了一個它所包含的索引項的序列嫩海。也就是說文檔指向了它包含的那些單詞冬殃,而反向索引則是單詞指向了包含它的文檔,很容易看到這個反向的關(guān)系叁怪。

擴(kuò)展:

問題實例:文檔檢索系統(tǒng)审葬,查詢那些文件包含了某單詞,比如常見的學(xué)術(shù)論文的關(guān)鍵字搜索骂束。

關(guān)于倒排索引的應(yīng)用耳璧,更多請參見:

第二十三、四章:楊氏矩陣查找展箱,倒排索引關(guān)鍵詞Hash不重復(fù)編碼實踐

第二十六章:基于給定的文檔生成倒排索引的編碼與實踐蹬昌。

密匙五混驰、外排序

適用范圍:大數(shù)據(jù)的排序,去重

基本原理及要點(diǎn):外排序的歸并方法皂贩,置換選擇敗者樹原理栖榨,最優(yōu)歸并樹

問題實例:

1).有一個1G大小的一個文件,里面每一行是一個詞明刷,詞的大小不超過16個字節(jié)婴栽,內(nèi)存限制大小是1M。返回頻數(shù)最高的100個詞辈末。

這個數(shù)據(jù)具有很明顯的特點(diǎn)愚争,詞的大小為16個字節(jié)映皆,但是內(nèi)存只有1M做hash明顯不夠,所以可以用來排序轰枝。內(nèi)存可以當(dāng)輸入緩沖區(qū)使用捅彻。

關(guān)于多路歸并算法及外排序的具體應(yīng)用場景,請參見blog內(nèi)此文:

第十章鞍陨、如何給10^7個數(shù)據(jù)量的磁盤文件排序

密匙六步淹、分布式處理之Mapreduce

MapReduce是一種計算模型,簡單的說就是將大批量的工作(數(shù)據(jù))分解(MAP)執(zhí)行诚撵,然后再將結(jié)果合并成最終結(jié)果(REDUCE)缭裆。這樣做的好處是可以在任務(wù)被分解后,可以通過大量機(jī)器進(jìn)行并行計算寿烟,減少整個操作的時間幼驶。但如果你要我再通俗點(diǎn)介紹,那么韧衣,說白了盅藻,Mapreduce的原理就是一個歸并排序。

適用范圍:數(shù)據(jù)量大畅铭,但是數(shù)據(jù)種類小可以放入內(nèi)存

基本原理及要點(diǎn):將數(shù)據(jù)交給不同的機(jī)器去處理氏淑,數(shù)據(jù)劃分,結(jié)果歸約硕噩。問題實例:

The canonical example application of MapReduce is a process to count the appearances of each different word in a set of documents:

海量數(shù)據(jù)分布在100臺電腦中假残,想個辦法高效統(tǒng)計出這批數(shù)據(jù)的TOP10。

一共有N個機(jī)器炉擅,每個機(jī)器上有N個數(shù)辉懒。每個機(jī)器最多存O(N)個數(shù)并對它們操作。如何找到N^2個數(shù)的中數(shù)(median)谍失?

更多具體闡述請參見blog內(nèi):

從Hadhoop框架與MapReduce模式中談海量數(shù)據(jù)處理眶俩,

MapReduce技術(shù)的初步了解與學(xué)習(xí)

其它模式/方法論快鱼,結(jié)合操作系統(tǒng)知識

至此颠印,六種處理海量數(shù)據(jù)問題的模式/方法已經(jīng)闡述完畢。據(jù)觀察抹竹,這方面的面試題無外乎以上一種或其變形线罕,然題目為何取為是:秒殺99%的海量數(shù)據(jù)處理面試題,而不是100%呢窃判。OK钞楼,給讀者看最后一道題,如下:

非常大的文件袄琳,裝不進(jìn)內(nèi)存询件。每行一個int類型數(shù)據(jù)燃乍,現(xiàn)在要你隨機(jī)取100個數(shù)。

我們發(fā)現(xiàn)上述這道題雳殊,無論是以上任何一種模式/方法都不好做橘沥,那有什么好的別的方法呢?我們可以看看:操作系統(tǒng)內(nèi)存分頁系統(tǒng)設(shè)計(說白了夯秃,就是映射+建索引)座咆。

Windows 2000使用基于分頁機(jī)制的虛擬內(nèi)存。每個進(jìn)程有4GB的虛擬地址空間仓洼〗樘眨基于分頁機(jī)制,這4GB地址空間的一些部分被映射了物理內(nèi)存色建,一些部分映射硬盤上的交換文 件哺呜,一些部分什么也沒有映射。程序中使用的都是4GB地址空間中的虛擬地址箕戳。而訪問物理內(nèi)存某残,需要使用物理地址。 關(guān)于什么是物理地址和虛擬地址陵吸,請看:

物理地址 (physical address): 放在尋址總線上的地址玻墅。放在尋址總線上,如果是讀壮虫,電路根據(jù)這個地址每位的值就將相應(yīng)地址的物理內(nèi)存中的數(shù)據(jù)放到數(shù)據(jù)總線中傳輸澳厢。如果是寫,電路根據(jù)這個 地址每位的值就將相應(yīng)地址的物理內(nèi)存中放入數(shù)據(jù)總線上的內(nèi)容囚似。物理內(nèi)存是以字節(jié)(8位)為單位編址的剩拢。

虛擬地址 (virtual address): 4G虛擬地址空間中的地址,程序中使用的都是虛擬地址饶唤。?使用了分頁機(jī)制之后徐伐,4G的地址空間被分成了固定大小的頁,每一頁或者被映射到物理內(nèi)存搬素,或者被映射到硬盤上的交換文件中呵晨,或者沒有映射任何東西。對于一 般程序來說熬尺,4G的地址空間,只有一小部分映射了物理內(nèi)存谓罗,大片大片的部分是沒有映射任何東西粱哼。物理內(nèi)存也被分頁,來映射地址空間檩咱。對于32bit的 Win2k揭措,頁的大小是4K字節(jié)胯舷。CPU用來把虛擬地址轉(zhuǎn)換成物理地址的信息存放在叫做頁目錄和頁表的結(jié)構(gòu)里。

物理內(nèi)存分頁绊含,一個物理頁的大小為4K字節(jié)桑嘶,第0個物理頁從物理地址 0x00000000 處開始。由于頁的大小為4KB躬充,就是0x1000字節(jié)逃顶,所以第1頁從物理地址 0x00001000 處開始。第2頁從物理地址 0x00002000 處開始充甚∫哉可以看到由于頁的大小是4KB,所以只需要32bit的地址中高20bit來尋址物理頁伴找。

返回上面我們的題目:非常大的文件盈蛮,裝不進(jìn)內(nèi)存。每行一個int類型數(shù)據(jù)技矮,現(xiàn)在要你隨機(jī)取100個數(shù)抖誉。針對此題,我們可以借鑒上述操作系統(tǒng)中內(nèi)存分頁的設(shè)計方法衰倦,做出如下解決方案:

操作系統(tǒng)中的方法袒炉,先生成4G的地址表,在把這個表劃分為小的4M的小文件做個索引耿币,二級索引梳杏。30位前十位表示第幾個4M文件,后20位表示在這個4M文件的第幾個淹接,等等十性,基于key value來設(shè)計存儲,用key來建索引塑悼。

但如果現(xiàn)在只有10000個數(shù)劲适,然后怎么去隨機(jī)從這一萬個數(shù)里面隨機(jī)取100個數(shù)?請讀者思考厢蒜。更多海里數(shù)據(jù)處理面試題霞势,請參見此文第一部分:http://blog.csdn.net/v_july_v/article/details/6685962

參考文獻(xiàn)

十道海量數(shù)據(jù)處理面試題與十個方法大總結(jié)斑鸦;

海量數(shù)據(jù)處理面試題集錦與Bit-map詳解愕贡;

十一、從頭到尾徹底解析Hash表算法巷屿;

海量數(shù)據(jù)處理之Bloom Filter詳解固以;

從Trie樹(字典樹)談到后綴樹

第三章續(xù)、Top K算法問題的實現(xiàn)憨琳;

第十章诫钓、如何給10^7個數(shù)據(jù)量的磁盤文件排序

從B樹篙螟、B+樹菌湃、B*樹談到R 樹

第二十三遍略、四章:楊氏矩陣查找惧所,倒排索引關(guān)鍵詞Hash不重復(fù)編碼實踐

第二十六章:基于給定的文檔生成倒排索引的編碼與實踐墅冷;

從Hadhoop框架與MapReduce模式中談海量數(shù)據(jù)處理纯路;

第十六~第二十章:全排列,跳臺階寞忿,奇偶排序驰唬,第一個只出現(xiàn)一次等問題

http://blog.csdn.net/v_JULY_v/article/category/774945腔彰;

STL源碼剖析第五章叫编,侯捷著;

2012百度實習(xí)生招聘筆試題:http://blog.csdn.net/hackbuteer1/article/details/7542774霹抛。

后記

經(jīng)過上面這么多海量數(shù)據(jù)處理面試題的轟炸搓逾,我們依然可以看出這類問題是有一定的解決方案/模式的,所以杯拐,不必將其神化霞篡。然這類面試題所包含的問題還是比較簡單的,若您在這方面有更多實踐經(jīng)驗端逼,歡迎隨時來信與我不吝分享:zhoulei0907@yahoo.cn朗兵。當(dāng)然,自會注明分享者及來源顶滩。

不過余掖,相信你也早就意識到,若單純論海量數(shù)據(jù)處理面試題礁鲁,本blog內(nèi)的有關(guān)海量數(shù)據(jù)處理面試題的文章已涵蓋了你能在網(wǎng)上所找到的70~80%盐欺。但有點(diǎn),必須負(fù)責(zé)任的敬告大家:無論是這些海量數(shù)據(jù)處理面試題也好仅醇,還是算法也好冗美,面試時,70~80%的人不是倒在這兩方面析二,而是倒在基礎(chǔ)之上(諸如語言墩衙,數(shù)據(jù)庫,操作系統(tǒng)甲抖,網(wǎng)絡(luò)協(xié)議等等)漆改,所以,無論任何時候准谚,基礎(chǔ)最重要挫剑,沒了基礎(chǔ),便什么都不是柱衔。

最后樊破,推薦國外一面試題網(wǎng)站:http://www.careercup.com/,以及個人正在讀的Redis/MongoDB絕佳站點(diǎn):http://blog.nosqlfan.com/唆铐。

OK哲戚,本文若有任何問題,歡迎隨時不吝留言艾岂,評論顺少,賜教鹤啡,謝謝稿黍。完捏肢。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牺陶,一起剝皮案震驚了整個濱河市乡恕,隨后出現(xiàn)的幾起案子洼滚,更是在濱河造成了極大的恐慌速梗,老刑警劉巖枚碗,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钞啸,死亡現(xiàn)場離奇詭異几蜻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)体斩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進(jìn)店門梭稚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人硕勿,你說我怎么就攤上這事哨毁。” “怎么了源武?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵扼褪,是天一觀的道長。 經(jīng)常有香客問我粱栖,道長话浇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任闹究,我火速辦了婚禮幔崖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己赏寇,他們只是感情好吉嫩,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嗅定,像睡著了一般自娩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上渠退,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天忙迁,我揣著相機(jī)與錄音,去河邊找鬼碎乃。 笑死姊扔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梅誓。 我是一名探鬼主播恰梢,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼证九!你這毒婦竟也來了删豺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤愧怜,失蹤者是張志新(化名)和其女友劉穎呀页,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拥坛,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蓬蝶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了猜惋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丸氛。...
    茶點(diǎn)故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖著摔,靈堂內(nèi)的尸體忽然破棺而出缓窜,到底是詐尸還是另有隱情,我是刑警寧澤谍咆,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布禾锤,位于F島的核電站,受9級特大地震影響摹察,放射性物質(zhì)發(fā)生泄漏恩掷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一供嚎、第九天 我趴在偏房一處隱蔽的房頂上張望黄娘。 院中可真熱鬧峭状,春花似錦、人聲如沸逼争。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氮凝。三九已至羔巢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間罩阵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工启摄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稿壁,地道東北人。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓歉备,卻偏偏與公主長得像傅是,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蕾羊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容