我正在寫一個程序比需要找到一組號碼中的第N個最大的值算出一組號碼在第N個最大值。這些數字是由程序生成的,但我沒有足夠的內存來存儲N個數字。是否有比N更好的上限,可以存儲?這組數字(和N)的大小的上限約爲100,000,000。因爲它們產生
注:數字是小數和列表可以包括重複。
[編輯]:我的內存限制爲16 MB。
我正在寫一個程序比需要找到一組號碼中的第N個最大的值算出一組號碼在第N個最大值。這些數字是由程序生成的,但我沒有足夠的內存來存儲N個數字。是否有比N更好的上限,可以存儲?這組數字(和N)的大小的上限約爲100,000,000。因爲它們產生
注:數字是小數和列表可以包括重複。
[編輯]:我的內存限制爲16 MB。
這是一種多通道算法(因此,您必須能夠多次生成相同的列表,或將列表存儲到輔助存儲中)。
第一遍:
通行證:
最後一關:
例如:如果你看到的範圍是0.0到1000.0,你的垃圾箱的範圍將是:
(- 0.0 - 100.0]
(100.0 - 200.0]
(200.0 - 300.0]
...
(900.0 - 1000.0)
如果你通過你的電話號碼爲(100.0計數發現 - 2000.0]斌,你的下集箱的將是:
(100.0 - 110.0]
(110.0 - 120.0]
etc.
另一種多通道的想法:
只需進行二分查找。選擇範圍的中點作爲第一次猜測。你的通行證只需要做一個高於/低於計數來確定下一個估計值(可以通過計數來加權,或者爲簡化代碼而簡單地進行平均)。
如果我理解好,您的程序上限的內存使用情況是O(N)(可能N + 1)。您可以維護生成的值的列表,該列表比當前X(迄今爲止的第N個最大值)大,按照最低的順序排列。只要生成一個新的更大的值,就可以將當前的X替換爲列表的第一個元素,並將剛剛生成的值插入列表中的相應位置。
這類似於另一個問題 - C Program to search n-th smallest element in array without sorting? - 在這裏你可以得到一些答案。
該邏輯將同樣適用於第N大/最小的搜索。
注意:我不是說這是重複的。
由於您有很多(接近10億?)數字,這裏是空間優化的另一種方法。
假設您的數字適合32位值,那麼大約10億將需要一段時間接近32GB的空間。現在,如果您可以承受大約128MB的工作內存,我們可以一次完成。
您能夠再生同一組從開始的數字?如果是的話,可以在輸出上多次傳遞:首先找到最大值,重新啓動發生器,找到最小的數字,重新啓動發生器,並重復此操作直到得到結果。
這將是一個真正的表現殺手,因爲你有很多數字,並且需要很多通行證 - 但是在記憶方面,你只需要存儲2個元素(當前最大值和一個「限制「,你在上一次傳球中找到的號碼)和一個傳球計數器。
您可以通過使用優先級隊列找到M個最大元素加快它(選擇數μm,你能夠裝入內存),讓您減少需要N/M的遍數。
如果您需要查找15個數字列表中的第10個最大元素,則可以通過其他方式節省時間。由於它是第10大元素,這意味着有15-10 = 5個元素比這個元素小 - 所以你可以找第6個最小的元素來代替。
我這樣做了使用最小堆優先級隊列,但我內存不足。 – snake 2009-07-05 16:38:21
然後你沒有足夠的內存來解決你的問題。我不認爲你能比存儲前N個號碼做得更好。 – PanCrit 2009-07-05 16:49:53