有10億個整數,要求選取重複次數最多的100個整數
要解答這個問題,首先要弄清楚下面幾個條件。
(1)有記憶體限制嗎?
(2)整數的範圍是多少?有符號,無符號,32位還是64位?
(3)整數集的內容大嗎?(即出現的整數空間的大小大嗎?)
(4)如果只需要求模糊解,怎麼解?
(5)求陣列中的第k大元素?
(7)相關問題:有乙個整數陣列,請求出兩兩之差絕對值最小的值,記住,只要得出最小值即可,不需要求出是哪兩個數。
(1)如果沒有記憶體限制,且假設是32位無符號的整數。最方便的辦法就是建立乙個整形陣列,inthash[2^32](贊不考慮程式的虛位址空間上限),然後對這10億個數進行一次遍歷,這樣,可以得到這2^32個數各自出現的次數,再對這個hash陣列進行取第k大元素,100次後,就可以取出這出現次數最多的前100個數。遍歷10億個數的時間複雜度是o(n),n=10^10,求第k大元素的時間複雜度是o(m),m=2^32(=4294967296),那麼本演算法的時間複雜度是o(n),空間複雜度是o(s),s=2^32。記憶體要2^32*4=16g
(2)如果有記憶體限制,或者必須滿足程式虛位址空間上限。那麼可以對整數空間進行分段處理,比如只提供512m記憶體,則將2^32個整數劃分成32個空間0~2^(27)-1,2^(27)~2^(28)-1,...,31*2^(27)~2^(32)-1。對原來的10億個數遍歷32次,每次遍歷,得到每個空間的整數的出現次數,並求出此空間中,出現次數最多的前100個整數,儲存下來。這樣32次之後,就得到了出現次數前3200的整數,再對這3200個整數取第k大元素,得到出現次數最多的前100個整數。這個演算法的時間複雜度也是o(n),空間複雜度降低多少不知道,但是記憶體使用降低不少。
(3)如果整數空間比較小,也就是說這10億個數中有很多重複的數,最方便的辦法估計就是維護乙個hashtable物件ht,key就是整數值,value就是該整數值出現的次數。遍歷這10億個元素,得到ht後再對這個ht求第k大元素。那麼這個演算法的時間複雜度就是o(n),n=10^10,空間複雜度是o(m),m為整數空間大小。
(4)隨機取樣(或者將原來的順序打亂,然後再順序取樣)。對樣本中的整數進行出現次數的統計,這個時候採用hashtable的辦法最好,時間複雜度是o(n)。如果對使用的空間有所限制,那麼只能對該樣本進行排序,再對排序後的樣本進行100次遍歷得到出現次數最多的前100個整數,則時間複雜度是o(nlogn),空間複雜度是o(1)。
(5)好像有兩種演算法。假設要求陣列a[1...n]中第k大元素。(a
)遞迴快排演算法。若
n <44
(經驗值)則直接排序返回第
k大元素,否則,將1到
n分成n/5個組,每個組
5個元素,然後求這
n/5個組的每組的中項元素,再求這
n/5個中項元素的中項元素mm(注意,這裡也可以用遞迴呼叫自身的方法)。然後對陣列a根據mm分成三組,a1中的所有元素小於mm,a2中的所有元素等於mm,a3中的所有元素大於mm,如果|a1|>=k,則第k大元素在a1中,如果|a1|+|a2|>=k|a1|,則第k大元素就是mm,如果k>|a1|+|a2|,則第k大元素在a3中,再繼續遞迴呼叫。這個演算法的時間複雜度是o(n)。(注意,這裡的中項mm也可以隨機選擇a中的元素,其時間複雜度也近似於o(n),而且係數也比較小)。 (
b)基於位查詢(僅對於無符號整數的查詢)。將
32位整數的二進位制位分為
4段,每段
8位,先比較
a中所有元素高
8位,找出第
k大元素高
8位的範圍,再對應這高8位的範圍在次高八位中找第k大元素的範圍,...這樣4次之後就可以找到第k大元素的。可以舉個例子便於理解,在10個3位整數中找第k大元素,將3位分成3段,每段1位,每位之可能是0,1。如果這10個數的最高位0的個數m大於等於k,則第k大元素的最高位為0,再在最高位為0的元素中找次高位為第k大元素;如果10個數中最高位0的個數m大於k,則在最高位為1的元素中找此高位為第m-k大元素。...
(6)這個問題是前面那個問題的特例。有沒有特殊的解法使效率又提高一些呢?我覺得沒有,因為1和100本來就是常數級,和n比它們的差別是忽略不計的。
(7)簡單的解法是對這個陣列排序,然後再對排好序的陣列進行一次遍歷就可得到兩兩絕對值最差的最小值,時間複雜度是o(nlogn)。網上說求a的min,max和長度n,如果dmax = (max-min+1)/n = 0,那麼就說明陣列a中有重複的元素,直接返回0。但是如果dmax =(max-min+1)/n >0,那麼就以dmax為箱的長度裝入a的元素,再在箱內和箱間比較。我不懂為什麼,但是這個空間複雜度是o(max),而且好像如果a是1, 2,3...100,那麼dmax就是1了,那麼a不是沒有動嗎?還有人說夠找陣列b,b[i] = a[i] -a[i+1],則a[i]-a[j]=b[i]+b[i+1]+...+b[j-1]也不知下文了,看來這個題比較搞啊。就是奧賽題,bs。
有10億個整數,要求選取重複次數最多的100個整數
要解答這個問題,首先要弄清楚下面幾個條件。1 有記憶體限制嗎?2 整數的範圍是多少?有符號,無符號,32位還是 64位?3 整數集的內容大嗎?即出現的整數空間的大小大嗎?4 如果只需要求模糊解,怎麼解?5 求陣列中的第 k大元素?6 相關問題 求乙個整數列 現次數最多的整數 7 相關問題 有乙個整數...
求陣列中重複次數最多的元素
例如 陣列a 元素2 3 7 8各出現1次,1出現兩次,5出現4次,則重複次數最多的元素為5.定義乙個陣列int cnt max 將其元素全部初始化為0。然後遍歷陣列a,執行cnt a i 操作。最後在cnt陣列中找最大的數,對應的數即為重複次數最多的數。示例如下 以空間換時間,索引法 int ma...
java實現列印list中重複次數最多的前n個資料
如 list中有1,3,4,5,1,7,5,3,4,2,1,5,1 當輸入輸入引數n為1時,列印1 當輸入引數n為2時,列印1,5 public void printtopn listnumbers,int n else 將統計出來的map進行處理 map resultmap new hashmap...