1. 程式人生 > >有10億個整數,要求選取重複次數最多的100個整數

有10億個整數,要求選取重複次數最多的100個整數

(1)如果沒有記憶體限制,且假設是32位無符號的整數。最方便的辦法就是建立一個整形陣列,int hash[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 (每個整型佔4byte)
     (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|&gt;=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。