問題是這樣的:
http://topic.csdn.net/u/20080604/16/95508149-b7a2-4f90-8797-b8423dae36fc.html
10億個浮點數中,找出最大的10個浮點數,寫出一個高效能演算法。
以下是區區逛論壇時的回答:“
很面熟的類型,使用stl::map來做 filter,複雜度是O(log(k) * n),這裡n為10^9,為10。
程中的不變數是 amap.size() <=k ,注意編寫實現就可以了。”
可是過了一會兒後,區區覺得這個回答雖然沒有方向性錯誤,卻是一個錯誤的回答。
所以區區花了很多時間實現自己的回答,最終的演算法實現讓自己很意外:
#include<iostream>
#include<iomanip>
#include<set>
using namespace std;
float genNext()
{
return rand()*1.0*rand() + rand();
}
int main()
{
multiset<float> kmax;
for(int ij=0; ij<10; ++ij)
kmax.insert(genNext());
for(int j=0; j<10; ++j)
for(int i=0; i<100000000 ;++i) {
float t = genNext();
if (*(kmax.begin()) < t) {
kmax.insert(t);
kmax.erase(kmax.begin());
}
}
multiset<float>::iterator iter=kmax.begin(),end=kmax.end();
for(; iter!=end; ++iter)
cout<<*iter<<endl;
return 0;
}
以前都把ACM演算法題當飯後練習的,想到這個演算法其實只不過是一眨眼的功夫。
然而在實現這個小小的想法過程是,問題一個接一個地出現,需要處理:
- 如果使用map,會浪費多餘空間,哪怕只有O(k),k=10~
- 實現上如果輸入集是可重複的話,用multiset才是正確的
- 說有10億個記憶體輸入是不實際的,產生幾G的測試檔案更是可笑,於是用generator: genNext()
- rand()是個耗時的操作,所以genNext()使人(區區在下)對演算法的時間期望有所誤判
- 10億真的是個煩人的數量級,用int迴圈得分成兩部份寫
- 由於上述誤判,一度花時間改用vector加std::push_heap和std::pop_heap來實現
- 所有其它的細節…………
現在回想起來,只有注意編寫實現是正確的。
區區現在試用著KompoZer來寫這個Blog,差不多是3小時後的事情了。
以後再有人問在下:“你一天能寫多少行代碼?”
回答是:“運氣好的話,15行。”