[轉(zhuǎn)]Consistent Hashing

引入

在業(yè)務(wù)開發(fā)中,我們常把數(shù)據(jù)持久化到數(shù)據(jù)庫中悠轩。如果需要讀取這些數(shù)據(jù)间狂,除了直接從數(shù)據(jù)庫中讀取外,為了減輕數(shù)據(jù)庫的訪問壓力以及提高訪問速度火架,我們更多地引入緩存來對數(shù)據(jù)進行存取鉴象。
讀取數(shù)據(jù)的過程一般為:

加入緩存的數(shù)據(jù)讀取過程.png

對于分布式緩存,不同機器上存儲不同對象的數(shù)據(jù)何鸡。為了實現(xiàn)這些緩存機器的負(fù)載均衡纺弊,可以使用式子1來定位對象緩存的存儲機器:

m = hash(o) mod n ——式子1

其中,o為對象的名稱骡男,n為機器的數(shù)量淆游,m為機器的編號,hash為一hash函數(shù)隔盛。圖2中的負(fù)載均衡器(load balancer)正是使用式子1來將客戶端對不同對象的請求分派到不同的機器上執(zhí)行犹菱,例如,對于對象o骚亿,經(jīng)過式子1的計算已亥,得到m的值為3,那么所有對對象o的讀取和存儲的請求都被發(fā)往機器3執(zhí)行来屠。

如何利用Hash取模實現(xiàn)負(fù)載均衡.png

式子1在大部分時候都可以工作得很好,然而,當(dāng)機器需要擴容或者機器出現(xiàn)宕機的情況下俱笛,事情就比較棘手了捆姜。
當(dāng)機器擴容,需要增加一臺緩存機器時迎膜,負(fù)載均衡器使用的式子變成:

m = hash(o) mod (n + 1) ——式子2

當(dāng)機器宕機泥技,機器數(shù)量減少一臺時,負(fù)載均衡器使用的式子變成:

m = hash(o) mod (n - 1) ——式子3

我們以機器擴容的情況為例磕仅,說明簡單的取模方法會導(dǎo)致什么問題珊豹。
假設(shè)機器由3臺變成4臺,對象o1由式子1計算得到的m值為2榕订,由式子2計算得到的m值卻可能為0店茶,1,2劫恒,3(一個 3t + 2的整數(shù)對4取模贩幻,其值可能為0,1两嘴,2丛楚,3,讀者可以自行驗證)憔辫,大約有75%(3/4)的可能性出現(xiàn)緩存訪問不命中的現(xiàn)象趣些。

隨著機器集群規(guī)模的擴大,這個比例線性上升贰您。當(dāng)99臺機器再加入1臺機器時喧务,不命中的概率是99%(99/100)。這樣的結(jié)果顯然是不能接受的枉圃,因為這會導(dǎo)致數(shù)據(jù)庫訪問的壓力陡增功茴,嚴(yán)重情況,還可能導(dǎo)致數(shù)據(jù)庫宕機孽亲。

一致性hash算法正是為了解決此類問題的方法坎穿,它可以保證當(dāng)機器增加或者減少時,對緩存訪問命中的概率影響減至很小返劲。

一致性哈希算法在1997年由麻省理工學(xué)院提出的一種分布式哈希(DHT)實現(xiàn)算法玲昧,設(shè)計目標(biāo)是為了解決因特網(wǎng)中的熱點(Hot spot)問題,初衷和CARP十分類似篮绿。一致性哈希修正了CARP使用的簡 單哈希算法帶來的問題孵延,使得分布式哈希(DHT)可以在P2P環(huán)境中真正得到應(yīng)用。
一致性hash算法提出了在動態(tài)變化的Cache環(huán)境中亲配,判定哈希算法好壞的四個定義:平衡性尘应,單調(diào)性惶凝,分散性,負(fù)載

下面我們來詳細(xì)說一下一致性hash算法的具體過程犬钢。

一致性Hash環(huán)

一致性hash算法通過一個叫作一致性hash環(huán)的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)苍鲜。
這個環(huán)的起點是0,終點是2^32 - 1玷犹,并且起點與終點連接混滔,環(huán)的中間的整數(shù)按逆時針分布,故這個環(huán)的整數(shù)分布范圍是[0, 2^32-1]歹颓,
如下圖3所示:

一致性Hash環(huán).png

將對象放置到Hash環(huán)

假設(shè)現(xiàn)在我們有4個對象坯屿,分別為o1,o2巍扛,o3领跛,o4,使用hash函數(shù)計算這4個對象的hash值(范圍為0 ~ 2^32-1):

hash(o1) = m1
hash(o2) = m2
hash(o3) = m3
hash(o4) = m4

把m1电湘,m2隔节,m3,m4這4個值放置到hash環(huán)上寂呛,得到如下圖4:


放置了對象的一致性Hash環(huán).png

將機器放置到Hash環(huán)

使用同樣的hash函數(shù)怎诫,我們將機器也放置到hash環(huán)上。
假設(shè)我們有三臺緩存機器贷痪,分別為 c1幻妓,c2,c3劫拢,使用hash函數(shù)計算這3臺機器的hash值:

hash(c1) = t1
hash(c2) = t2
hash(c3) = t3

把t1肉津,t2,t3 這3個值放置到hash環(huán)上舱沧,得到如下圖5:


放置了機器的一致性Hash環(huán).png

為對象選擇機器

將對象和機器都放置到同一個hash環(huán)后妹沙,在hash環(huán)上順時針查找距離這個對象的hash值最近的機器,即是這個對象所屬的機器熟吏。

例如距糖,對于對象o2,順序針找到最近的機器是c1牵寺,故機器c1會緩存對象o2悍引。而機器c2則緩存o3,o4帽氓,機器c3則緩存對象o1趣斤。

在一致性Hash環(huán)上為對象選擇機器.png

處理機器增減的情況

對于線上的業(yè)務(wù),增加或者減少一臺機器的部署是常有的事情黎休。

例如浓领,增加機器c4的部署并將機器c4加入到hash環(huán)的機器c3與c2之間玉凯。這時,只有機器c3與c4之間的對象需要重新分配新的機器镊逝。對于我們的例子壮啊,只有對象o4被重新分配到了c4嫉鲸,其他對象仍在原有機器上撑蒜。如圖7所示:


增加機器后的一致性Hash環(huán)的結(jié)構(gòu).png

如上文前面所述,使用簡單的求模方法玄渗,當(dāng)新添加機器后會導(dǎo)致大部分緩存失效的情況座菠,使用一致性hash算法后這種情況則會得到大大的改善。

前面提到3臺機器變成4臺機器后藤树,緩存命中率只有25%(不命中率75%)浴滴。而使用一致性hash算法,理想情況下緩存命中率則有75%岁钓,而且升略,隨著機器規(guī)模的增加,命中率會進一步提高屡限,99臺機器增加一臺后品嚣,命中率達到99%,這大大減輕了增加緩存機器帶來的數(shù)據(jù)庫訪問的壓力钧大。

再例如翰撑,將機器c1下線(當(dāng)然,也有可能是機器c1宕機)啊央,這時眶诈,只有原有被分配到機器c1對象需要被重新分配到新的機器。

對于我們的例子瓜饥,只有對象o2被重新分配到機器c3逝撬,其他對象仍在原有機器上。

如圖8所示:


減少機器后的一致性Hash環(huán)的結(jié)構(gòu).png

虛擬節(jié)點

上面提到的過程基本上就是一致性hash的基本原理了乓土,不過還有一個小小的問題宪潮。新加入的機器c4只分擔(dān)了機器c2的負(fù)載,機器c1與c3的負(fù)載并沒有因為機器c4的加入而減少負(fù)載壓力帐我。如果4臺機器的性能是一樣的坎炼,那么這種結(jié)果并不是我們想要的。

為此拦键,我們引入虛擬節(jié)點來解決負(fù)載不均衡的問題谣光。

將每臺物理機器虛擬為一組虛擬機器,將虛擬機器放置到hash環(huán)上芬为,如果需要確定對象的機器萄金,先確定對象的虛擬機器蟀悦,再由虛擬機器確定物理機器。
說得有點復(fù)雜氧敢,其實過程也很簡單日戈。

還是使用上面的例子,
假如開始時存在緩存機器c1孙乖,c2浙炼,c3,對于每個緩存機器唯袄,都有3個虛擬節(jié)點對應(yīng)弯屈,
其一致性hash環(huán)結(jié)構(gòu)如圖9所示:


機器c1,c2恋拷,c3的一致性Hash環(huán)結(jié)構(gòu).png

假設(shè)對于對象o1资厉,其對應(yīng)的虛擬節(jié)點為c11,而虛擬節(jié)點c11對象緩存機器c1蔬顾,故對象o1被分配到機器c1中宴偿。

新加入緩存機器c4,其對應(yīng)的虛擬節(jié)點為c41诀豁,c42窄刘,c43,將這三個虛擬節(jié)點添加到hash環(huán)中且叁,得到的hash環(huán)結(jié)構(gòu)如圖10所示:


機器c1都哭,c2,c3逞带,c4的一致性Hash環(huán)結(jié)構(gòu).png

新加入的緩存機器c4對應(yīng)一組虛擬節(jié)點c41欺矫,c42,c43展氓,加入到hash環(huán)后穆趴,影響的虛擬節(jié)點包括c31,c22遇汞,c11(順時針查找到第一個節(jié)點)未妹,而這3個虛擬節(jié)點分別對應(yīng)機器c3,c2空入,c1络它。即新加入的一臺機器,同時影響到原有的3臺機器歪赢。

理想情況下化戳,新加入的機器平等地分擔(dān)了原有機器的負(fù)載,這正是虛擬節(jié)點帶來的好處埋凯。而且新加入機器c4后点楼,只影響25%(1/4)對象分配扫尖,也就是說,命中率仍然有75%掠廓,這跟沒有使用虛擬節(jié)點的一致性hash算法得到的結(jié)果是相同的换怖。

總結(jié)

一致性hash算法解決了分布式環(huán)境下機器增加或者減少時,簡單的取模運算無法獲取較高命中率的問題蟀瞧。

通過虛擬節(jié)點的使用沉颂,一致性hash算法可以均勻分擔(dān)機器的負(fù)載,使得這一算法更具現(xiàn)實的意義黄橘。

正因如此兆览,一致性hash算法被廣泛應(yīng)用于分布式系統(tǒng)中屈溉。

參考資料

  1. https://en.wikipedia.org/wiki/Consistent_hashing

  2. https://www.codeproject.com/articles/56138/consistent-hashing

  3. 《大型網(wǎng)站技術(shù)架構(gòu)——核心原理與安全分析》塞关,李智慧著,電子工業(yè)出版社


栗子:

栗子.png
海量數(shù)據(jù)處理

海量數(shù)據(jù)處理策略之一—Hash映射 + Hash_map統(tǒng)計 + 堆/快速/歸并排序子巾。
海量數(shù)據(jù)處理帆赢,就是基于海量數(shù)據(jù)的查找、統(tǒng)計线梗、運算等操作椰于。
海量數(shù)據(jù),就是數(shù)據(jù)量太大仪搔,導(dǎo)致要么無法在較短時間內(nèi)迅速解決瘾婿,要么數(shù)據(jù)太大,導(dǎo)致無法一次性裝入內(nèi)存烤咧。從而導(dǎo)致傳統(tǒng)的操作無法實現(xiàn)偏陪。

一、問題描述

海量日志數(shù)據(jù)煮嫌,提取出某日訪問百度次數(shù)最多的那個IP笛谦。

思路
由于數(shù)據(jù)集很大,我們的策略是先用哈希映射將海量數(shù)據(jù)集映射為適當(dāng)數(shù)量的非海量數(shù)據(jù)集昌阿,這個非海量數(shù)據(jù)集的大小足夠我們的計算機吃下饥脑。然后我們可用hash_map去對數(shù)據(jù)進行統(tǒng)計,最后根據(jù)統(tǒng)計數(shù)據(jù)采用堆/快速/歸并排序等方式找出最值懦冰。

1.在這里步驟一即哈希映射是將海量數(shù)據(jù)的大文件分割成小文件灶轰,因為內(nèi)存受限,計算機一口吃不下刷钢。

2.利用hash_map去對劃分后的小文件進行頻率統(tǒng)計.

3.統(tǒng)計完成后在利用排序算法找出訪問頻率最大值的IP
具體實現(xiàn):理論上的2的32次方個IP笋颤,我們可以采用哈希映射的方法,比如將IP換成整數(shù)去對1000取模闯捎,取模的值將會落在集合[0…999]中椰弊,每個值對應(yīng)著一個集合许溅,于是將由1000個集合,我們把取模后得到這個值的IP追加劃分到該集合中去秉版。接下來就是對每個小IP集合文件利用hash_map進行頻率統(tǒng)計贤重,利用排序算法找出各個文件中的最大值,最后對這些所謂的最大值再找出真正的最大值清焕。

二并蝗、為什么要用哈希映射

為了能在有限的計算機內(nèi)存資源下處理海量大數(shù)據(jù),我們必須通過某種機制將大文件映射為小文件秸妥,這種機制就是散列滚停,他通常將數(shù)據(jù)均勻地散列到各個子文件中去,這種映射散列的方式叫做哈希函數(shù)粥惧,好的哈希函數(shù)通常還能將數(shù)據(jù)均勻分布減少沖突键畴。

三、題目

題目:每一個ip訪問百度突雪,其ip地址都會被記錄到后臺日志文件中起惕,假設(shè)一天的訪問日志有100G,求出一天中訪問百度次數(shù)最多的ip地址咏删,可以使用的內(nèi)存大小是1G惹想。

首先,我們將文件分解成小文件督函,題目說可使用大小我們不能就恰恰分成100個文件嘀粱,因為計算機上還有運行程序或存儲其他必要的資源,為了方便計算辰狡,我們將數(shù)據(jù)分成大小為100M一個的文件锋叨,這樣即分成1024個文件:[FILE 0……FILE1023],100M大小我們說是這么說搓译,但實際上并不會很均勻悲柱,一個好的哈希函數(shù)會大概將數(shù)據(jù)均分分配到各個子文件中去。于是這樣就解決了因為計算機內(nèi)存有些而數(shù)據(jù)海量不能一次性讀入計算機的問題些己。

然后豌鸡,我們對小文件中的IP利用hash_map進行統(tǒng)計,求出每個文件中IP出現(xiàn)次數(shù)最大的值段标。

最后涯冠,對這1024個子文件中的IP出現(xiàn)次數(shù)最多的再來一輪IP次數(shù)出現(xiàn)最多的求法,即可求得整個海量數(shù)據(jù)下出現(xiàn)次數(shù)最多的IP逼庞。

第一部分蛇更、十道海量數(shù)據(jù)處理面試題
1、海量日志數(shù)據(jù),提取出某日訪問百度次數(shù)最多的那個IP派任。

首先是這一天砸逊,并且是訪問百度的日志中的IP取出來,逐個寫入到一個大文件中掌逛。注意到IP是32位的师逸,最多有個2^32個IP。同樣可以采用映射的方法豆混,比如模1000篓像,把整個大文件映射為1000個小文件,再找出每個小文中出現(xiàn)頻率最大的IP(可以采用hash_map進行頻率統(tǒng)計皿伺,然后再找出頻率最大的幾個)及相應(yīng)的頻率员辩。然后再在這1000個最大的IP中,找出那個頻率最大的IP鸵鸥,即為所求奠滑。

或者如下闡述(雪域之鷹):
算法思想:分而治之+Hash
1.IP地址最多有2^32=4G種取值情況,所以不能完全加載到內(nèi)存中處理脂男;
2.可以考慮采用“分而治之”的思想养叛,按照IP地址的Hash(IP)24值,把海量IP日志分別存儲到1024個小文件中宰翅。這樣,每個小文件最多包含4MB個IP地址爽室;
3.對于每一個小文件汁讼,可以構(gòu)建一個IP為key,出現(xiàn)次數(shù)為value的Hash map阔墩,同時記錄當(dāng)前出現(xiàn)次數(shù)最多的那個IP地址嘿架;
4.可以得到1024個小文件中的出現(xiàn)次數(shù)最多的IP,再依據(jù)常規(guī)的排序算法得到總體上出現(xiàn)次數(shù)最多的IP啸箫;

2耸彪、搜索引擎會通過日志文件把用戶每次檢索使用的所有檢索串都記錄下來,每個查詢串的長度為1-255字節(jié)忘苛。

假設(shè)目前有一千萬個記錄(這些查詢串的重復(fù)度比較高蝉娜,雖然總數(shù)是1千萬,但如果除去重復(fù)后扎唾,不超過3百萬個召川。一個查詢串的重復(fù)度越高,說明查詢它的用戶越多胸遇,也就是越熱門荧呐。),請你統(tǒng)計最熱門的10個查詢串,要求使用的內(nèi)存不能超過1G倍阐。

典型的Top K算法概疆,還是在這篇文章里頭有所闡述,詳情請參見:十一峰搪、從頭到尾徹底解析Hash表算法届案。

文中,給出的最終算法是:
第一步罢艾、先對這批海量數(shù)據(jù)預(yù)處理楣颠,在O(N)的時間內(nèi)用Hash表完成統(tǒng)計(之前寫成了排序,特此訂正咐蚯。July童漩、2011.04.27);
第二步春锋、借助堆這個數(shù)據(jù)結(jié)構(gòu)矫膨,找出Top K,時間復(fù)雜度為N‘logK期奔。
即侧馅,借助堆結(jié)構(gòu),我們可以在log量級的時間內(nèi)查找和調(diào)整/移動呐萌。因此馁痴,維護一個K(該題目中是10)大小的小根堆,然后遍歷300萬的Query肺孤,分別和根元素進行對比所以罗晕,我們最終的時間復(fù)雜度是:O(N) + N’*O(logK),(N為1000萬赠堵,N’為300萬)小渊。ok,更多茫叭,詳情酬屉,請參考原文。

或者:采用trie樹揍愁,關(guān)鍵字域存該查詢串出現(xiàn)的次數(shù)呐萨,沒有出現(xiàn)為0。最后用10個元素的最小推來對出現(xiàn)頻率進行排序吗垮。

3垛吗、有一個1G大小的一個文件,里面每一行是一個詞,詞的大小不超過16字節(jié),內(nèi)存限制大小是1M赃泡。返回頻數(shù)最高的100個詞着撩。

方案:順序讀文件中谒出,對于每個詞x忧饭,取hash(x)P00逾滥,然后按照該值存到5000個小文件(記為x0,x1,…x4999)中徐勃。這樣每個文件大概是200k左右羡儿。

如果其中的有的文件超過了1M大小礼患,還可以按照類似的方法繼續(xù)往下分,直到分解得到的小文件的大小都不超過1M掠归。
對每個小文件缅叠,統(tǒng)計每個文件中出現(xiàn)的詞以及相應(yīng)的頻率(可以采用trie樹/hash_map等),并取出出現(xiàn)頻率最大的100個詞(可以用含100個結(jié)點的最小堆)虏冻,并把100個詞及相應(yīng)的頻率存入文件肤粱,這樣又得到了5000個文件。下一步就是把這5000個文件進行歸并(類似與歸并排序)的過程了厨相。

4领曼、有10個文件,每個文件1G蛮穿,每個文件的每一行存放的都是用戶的query庶骄,每個文件的query都可能重復(fù)。要求你按照query的頻度排序践磅。

還是典型的TOP K算法单刁,解決方案如下:
方案1:
順序讀取10個文件,按照hash(query)的結(jié)果將query寫入到另外10個文件(記為)中音诈。這樣新生成的文件每個的大小大約也1G(假設(shè)hash函數(shù)是隨機的)幻碱。

找一臺內(nèi)存在2G左右的機器,依次對用hash_map(query, query_count)來統(tǒng)計每個query出現(xiàn)的次數(shù)细溅。利用快速/堆/歸并排序按照出現(xiàn)次數(shù)進行排序。將排序好的query和對應(yīng)的query_cout輸出到文件中儡嘶。這樣得到了10個排好序的文件(記為)喇聊。

對這10個文件進行歸并排序(內(nèi)排序與外排序相結(jié)合)。

方案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)赎线,最后再進行合并。

5糊饱、 給定a垂寥、b兩個文件,各存放50億個url另锋,每個url各占64字節(jié)滞项,內(nèi)存限制是4G,讓你找出a夭坪、b文件共同的url文判?

方案1:可以估計每個文件安的大小為5G×64=320G,遠(yuǎn)遠(yuǎn)大于內(nèi)存限制的4G台舱。所以不可能將其完全加載到內(nèi)存中處理律杠。考慮采取分而治之的方法竞惋。

遍歷文件a柜去,對每個url求取hash(url)00,然后根據(jù)所取得的值將url分別存儲到1000個小文件(記為a0,a1,…,a999)中拆宛。這樣每個小文件的大約為300M嗓奢。

遍歷文件b,采取和a相同的方式將url分別存儲到1000小文件(記為b0,b1,…,b999)浑厚。這樣處理后股耽,所有可能相同的url都在對應(yīng)的小文件(a0vsb0,a1vsb1,…,a999vsb999)中,不對應(yīng)的小文件不可能有相同的url钳幅。然后我們只要求出1000對小文件中相同的url即可物蝙。

求每對小文件中相同的url時,可以把其中一個小文件的url存儲到hash_set中敢艰。然后遍歷另一個小文件的每個url诬乞,看其是否在剛才構(gòu)建的hash_set中,如果是钠导,那么就是共同的url震嫉,存到文件里面就可以了。

方案2:如果允許有一定的錯誤率牡属,可以使用Bloom filter票堵,4G內(nèi)存大概可以表示340億bit。將其中一個文件中的url使用Bloom filter映射為這340億bit逮栅,然后挨個讀取另外一個文件的url悴势,檢查是否與Bloom filter窗宇,如果是,那么該url應(yīng)該是共同的url(注意會有一定的錯誤率)瞳浦。

Bloom filter日后會在本BLOG內(nèi)詳細(xì)闡述担映。

6、在2.5億個整數(shù)中找出不重復(fù)的整數(shù)叫潦,注蝇完,內(nèi)存不足以容納這2.5億個整數(shù)。

方案1:采用2-Bitmap(每個數(shù)分配2bit矗蕊,00表示不存在短蜕,01表示出現(xiàn)一次,10表示多次傻咖,11無意義)進行朋魔,共需內(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題類似的方法崭放,進行劃分小文件的方法哨苛。然后在小文件中找出不重復(fù)的整數(shù),并排序币砂。然后再進行歸并建峭,注意去除重復(fù)的元素。

7决摧、騰訊面試題:給40億個不重復(fù)的unsigned int的整數(shù)迹缀,沒排過序的,然后再給一個數(shù)蜜徽,如何快速判斷這個數(shù)是否在那40億個數(shù)當(dāng)中?

與上第6題類似票摇,我的第一反應(yīng)時快速排序+二分查找拘鞋。以下是其它更好的方法:
方案1:oo,申請512M的內(nèi)存矢门,一個bit位代表一個unsigned int值盆色。讀入40億個數(shù)灰蛙,設(shè)置相應(yīng)的bit位,讀入要查詢的數(shù)隔躲,查看相應(yīng)bit位是否為1摩梧,為1表示存在,為0表示不存在宣旱。

dizengrong:
方案2:這個問題在《編程珠璣》里有很好的描述仅父,大家可以參考下面的思路,探討一下:
又因為2^32為40億多浑吟,所以給定一個數(shù)可能在笙纤,也可能不在其中;
這里我們把40億個數(shù)中的每一個用32位的二進制來表示
假設(shè)這40億個數(shù)開始放在一個文件中组力。

然后將這40億個數(shù)分成兩類:
1.最高位為0
2.最高位為1
并將這兩類分別寫入到兩個文件中省容,其中一個文件中數(shù)的個數(shù)<=20億,而另一個>=20億(這相當(dāng)于折半了)燎字;
與要查找的數(shù)的最高位比較并接著進入相應(yīng)的文件再查找

再然后把這個文件為又分成兩類:
1.次最高位為0
2.次最高位為1

并將這兩類分別寫入到兩個文件中腥椒,其中一個文件中數(shù)的個數(shù)<=10億,而另一個>=10億(這相當(dāng)于折半了)候衍;
與要查找的數(shù)的次最高位比較并接著進入相應(yīng)的文件再查找笼蛛。
…….
以此類推,就可以找到了,而且時間復(fù)雜度為O(logn)脱柱,方案2完伐弹。

附:這里,再簡單介紹下榨为,位圖方法:
使用位圖法判斷整形數(shù)組是否存在重復(fù)
判斷集合中存在重復(fù)是常見編程任務(wù)之一惨好,當(dāng)集合中數(shù)據(jù)量比較大時我們通常希望少進行幾次掃描,這時雙重循環(huán)法就不可取了随闺。

位圖法比較適合于這種情況日川,它的做法是按照集合中最大元素max創(chuàng)建一個長度為max+1的新數(shù)組,然后再次掃描原數(shù)組矩乐,遇到幾就給新數(shù)組的第幾位置上1龄句,如遇到5就給新數(shù)組的第六個元素置1,這樣下次再遇到5想置位時發(fā)現(xiàn)新數(shù)組的第六個元素已經(jīng)是1了散罕,這說明這次的數(shù)據(jù)肯定和以前的數(shù)據(jù)存在著重復(fù)分歇。這種給新數(shù)組初始化時置零其后置一的做法類似于位圖的處理方法故稱位圖法。它的運算次數(shù)最壞的情況為2N欧漱。如果已知數(shù)組的最大值即能事先給新數(shù)組定長的話效率還能提高一倍职抡。

學(xué)習(xí)資料來源:
https://blog.csdn.net/u010710458/article/details/79717586
https://blog.csdn.net/lihao21/article/details/54193868
https://blog.csdn.net/sparkliang/article/details/5279393
https://blog.csdn.net/cywosp/article/details/23397179)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市误甚,隨后出現(xiàn)的幾起案子缚甩,更是在濱河造成了極大的恐慌谱净,老刑警劉巖擅威,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件郊丛,死亡現(xiàn)場離奇詭異宾袜,居然都是意外死亡,警方通過查閱死者的電腦和手機认轨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門嘁字,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纪蜒,“玉大人纯续,你說我怎么就攤上這事灭袁∪灼纾” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵逢唤,是天一觀的道長涤浇。 經(jīng)常有香客問我,道長吊奢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮裹驰,結(jié)果婚禮上片挂,老公的妹妹穿的比我還像新娘音念。我一直安慰自己闷愤,他們只是感情好讥脐,可當(dāng)我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布旬渠。 她就那樣靜靜地躺著告丢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪岳颇。 梳的紋絲不亂的頭發(fā)上觅捆,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天赦役,我揣著相機與錄音,去河邊找鬼栅炒。 笑死,一個胖子當(dāng)著我的面吹牛赢赊,可吹牛的內(nèi)容都是我干的乙漓。 我是一名探鬼主播释移,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼叭披,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涩蜘?” 一聲冷哼從身側(cè)響起嚼贡,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎同诫,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體误窖,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年柔吼,在試婚紗的時候發(fā)現(xiàn)自己被綠了艇棕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝌戒。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖打瘪,靈堂內(nèi)的尸體忽然破棺而出友鼻,到底是詐尸還是另有隱情,我是刑警寧澤闺骚,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布彩扔,位于F島的核電站,受9級特大地震影響僻爽,放射性物質(zhì)發(fā)生泄漏虫碉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一胸梆、第九天 我趴在偏房一處隱蔽的房頂上張望敦捧。 院中可真熱鬧,春花似錦碰镜、人聲如沸兢卵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秽荤。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窃款,已是汗流浹背课兄。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雁乡,地道東北人第喳。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像踱稍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子悠抹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,573評論 2 353