1.利用堆找出最大的K個數程序員
首先,先理解下用堆找出最大的K個數的經常使用解法,例如問題是「從M(M <= 10000)個數中找出最大的K個數」面試
(1)利用最大堆算法
創建一個N=M大小的大頂堆,而後輸出根節點以後,將根節點刪除,而後再將剩餘的元素調整成大頂堆;依次重複K次這個過程,最終就找出了K個最大的數。這實質上就是堆排序的過程。這種方法的時間複雜度爲O(K *logM)數據結構
(2)利用最小堆函數
這是最經常使用的一種方式,首先創建一個N=K大小的小頂堆,這K個元素能夠爲M中元素中的任意K個;咱們假設這K個元素就是最大的K個元素(其中根節點是這K個元素中最小的元素);那麼對於剩下的M-K個元素,咱們逐個與根節點進行對比,spa
若是當前元素大於根節點的元素的話,就將當前的元素與根節點的元素進行交換,而後將堆再次進行進行調整成最小堆,重複這個過程,直到比較完剩下的M-K個元素;那麼最終的小頂堆對應的K個數,必然是M個數中的最大的K個數。這種方法的.net
時間複雜度爲O(M*logK);而且方法2相對方法1而言,所須要的內存空間更小了,方法1創建的堆須要M個元素對應的內存空間,而方法2創建的堆只須要K個元素對應的內存空間,因此在對內存空間有嚴格要求的狀況下,採用方法2會更加好一些。blog
2.海量數據中找出最大的K個數排序
對於1而言,M這個指不能很大;若是M很大的話(好比M = 40億),就不能直接使用排序來找了。對於這種狀況,通常是利用「hash映射+堆」的過程,這裏的堆是指的方法2,具體以下:內存
將40億個數分紅若干小的部分(分紅多少部分要看題目對內從空間大小的限制),通常是利用哈希函數$h(x) = x% N$,其中N爲分紅的部分數;而後對於每一個小的部分,若是內存能夠一次性讀取的話,則利用堆採用方法2,選取每一個小部分數據中的TOPK個元素,一共
N*K個元素,而後繼續利用堆,採用方法2從這N*K個元素種找出最大的K個元素。
3.找出100億個URL中重複的URL
(1)對於這類問題,一般採用的的算法思想是「hash映射+哈希表」;大致而言,將100億個URL利用哈希函數分紅N個部分,每一個部分用哈希表進行統計次數,最終找到全部重複的URL。
(2)利用字典樹。
4.找出20億個數中出現次數最多的數
解決這類問題的想和3中的法(1)相似。
5.找出40億個非負整數中出現0次、1次...N次的數
通常找出非負整數中的出現多少次的數,都是利用BItMap
此處只是粗略的總結下,更詳細的總結可參考左神的《程序員代碼面試指南--IT名企算法與數據結構題目最優解》和July的http://www.javashuo.com/article/p-xfezyxuf-gb.html