騰訊 1億個資料取前1萬大的整數

2021-06-29 15:26:42 字數 1934 閱讀 9204

資料規模分析

不考慮作業系統的區別,通常將c++中的乙個整型變數認為4bytes。那麼1億整型需要400m左右的記憶體空間。當然,就現代pc機而言,連續開闢400m的記憶體空間還是可行的。因此,下面的討論只考慮在記憶體中的情況。為了討論方便,假設m=1億,n=1萬。

用大拇指想想

略微考慮一下,使用選擇排序。迴圈1萬次,每次選擇最大的元素。源**如下:

cpp**  

//解決方案1,簡單選擇排序

//bigarr存放1億的總資料、resarr存放1萬的總資料

void solution_1(int bigarr, int resarr )  

//將最大元素交換到開始位置

resarr[i] = bigarr[idx];  

std::swap( bigarr[idx], bigarr[i] );  

}  }  

效能分析:

哇靠!時間複雜度為o(m*n)。 有人做過實驗《從一道筆試題談演算法優化(上) 》,需要40分鐘以上的執行時間。太悲劇了......

當然,用先進的排序方法(比如快排),時間複雜度為o(m*logm)。雖然有很大的改進了,據說使用c++的stl中的快排方法只需要32秒左右。確實已經達到指數級的優化了,但是否還能夠優化呢?

稍微動下腦子

我們只需要1萬個最大的數,並不需要所有的數都有序,也就是說只要保證的9999萬個數比這1萬個數都小就ok了。我們可以通過下面的方法來該進:

(1) 先找出m資料中的前n個數。確定這n個數中的最小的數minelement。

(2) 將  (n+1) —— m個數迴圈與minelement比較,如果比minelement還小,則不處理。如果比minelement大,則與minelement交換,然後重新找出n個數中的minelement。

cpp**  

//解決方案2

void solution_2( t bigarr, t resarr )  

}  //這個後續元素比resarr中最小的元素大,則替換。

if( bigarr[i] > resarr[idx] )else

bexchanged = false;  

}  }  

效能分析:

最壞的時間複雜度為o((m-n)*n)。咋一看好像比快排的時間複雜度還高。但是注意是最壞的,實際上,並不是每次都需要付出乙個最小值o(n)的代價的。因為,如果當前的bigarr[i]如果m基本正序的話,則每次都要交換最小值,每次都要付出乙個o(n)代價。最壞的情況比快排還要差。

就平均效能而言,改進的演算法還是比快排要好的,其執行時間大約在2.0秒左右。

使勁動下腦子

上面的解決方案2還有乙個地方不太好。當bigarr[i]>resarr[idx]時,則必須交換這兩個數,進而每次都需要重新計算一輪n個數的最小值。只改變了乙個數就需要全部迴圈一次n實在是不划算。能不能下一次的最小值查詢可以借助上一次的比較結果呢?

基於這樣乙個想法,我們考慮到了堆排序的優勢(每一次調整堆都只需要比較logn的結點數量)。因此我們再做一次改進:

(1) 首先我們把前n個數建立成小頂堆,則根結點rootidx。

(2) 當bigarr[i]>resarr[rootidx]時,則交換這兩個數,並重新調整堆,使得根結點最小。

效能分析:顯然,除了第一次建堆需要o(n)時間的複雜度外,每一次調整堆都只需要o(logn)的時間複雜度。因此最壞情況下的時間複雜度為o((m-n)*logn),這樣即使在最壞情況下也比快排的o(m*logm)要好的多了。

另外:實際上也可以使用二分查詢的思想,第一次找n中的最小值的時候將n排序。以後每次替換最小值,都使用二分查詢在logn代價下找到當前n的最小值即可。與使用堆的過程如出一轍。

騰訊 1億個資料取前1萬大的整數

資料規模分析 不考慮作業系統的區別,通常將c 中的乙個整型變數認為4bytes。那麼1億整型需要400m左右的記憶體空間。當然,就現代pc機而言,連續開闢400m的記憶體空間還是可行的。因此,下面的討論只考慮在記憶體中的情況。為了討論方便,假設m 1億,n 1萬。用大拇指想想 略微考慮一下,使用選擇...

也論從1億個整數中找出最大的1萬個(下)

改寫adjust heap函式,讓要插入值與插入點的孩子節點進行比較判斷。template class distance,class tp,class compare inline void adjust heap tp first,distance holeindex,distance len,d...

mysql 取分組資料的前幾名(1)

目前有需求需要取分組資料的前幾名,有如下的解決方案來實現 具體資料庫如下 sql寫法 select from student grade as a where select coun from student grade as b where b.subid a.subid and b.grade ...