您能否提出一個有效的算法來從一組給定n個數字(未分類)中找到最小10個和最大10個數字?我想到的給定n個數字中的最小和最大10個數字
的一種方式將是對數組進行排序,然後從中挑選。
應該有更好的方法來做到這一點。
你能提出一種方法嗎?
這不是一個家庭作業問題。
您能否提出一個有效的算法來從一組給定n個數字(未分類)中找到最小10個和最大10個數字?我想到的給定n個數字中的最小和最大10個數字
的一種方式將是對數組進行排序,然後從中挑選。
應該有更好的方法來做到這一點。
你能提出一種方法嗎?
這不是一個家庭作業問題。
Python標準庫有這個工作,已經進行(heapq.nlargest和heapq.smallest)。
對於你的情況,它會制定出製作最小堆和最大堆與數據集的第10名成員預填充,然後進行在數據單次,必要時更新堆:
FOR element IN remaining_data
IF element > top_of_min_heap
THEN update_min_heap(element)
ENDIF
IF element < top_of_max_heap
THEN update_max_heap(element)
ENDIF
ENDFOR
的更新步取代現有的,最小的已經見過最大的最十最小的最十大,已經看到和。
這裏大致是Python標準庫中的代碼是什麼樣子:
def nlargest(n, iterable):
"""Find the n largest elements in a dataset.
Equivalent to: sorted(iterable, reverse=True)[:n]
"""
if n < 0:
return []
it = iter(iterable)
result = list(islice(it, n)) # pre-populate with the first n elements
if not result:
return result
heapify(result) # arrange them into a minheap
for elem in it:
if element > result[0]: # new elem is bigger than the smallest-of-the-large
heapreplace(result, elem) # replace top element with new element
result.sort() # sort the top ten
return result
你可能會想太多,你只需要一次掃描陣列和commparing的最大最小值和最大值最低它填補兩個陣列跟蹤10個最小值和10米的最大值。 O(n)
A sort has O(n log n)
是的。創建兩個大小爲k
(k=10
)的堆,其中一個用less
作爲比較器,另一個用more
。兩個有兩個存儲「top k」元素的結構。
查看每個元素並放入每個堆中。如果要素走出去堆的,忘記他們,這意味着他們不是在排名前10位
我相信這是所謂的Hadian - 索貝爾算法的一些變化。這是堆排序的基礎。有點像分區(我相信霍爾算法)快速排序。這也可以用在這裏順便說一句。
這樣你O(n) * 2 O(log k)
。 N
元素次數heap_insert
大小k
。這是O(n log k)
,對於k=10
基本上是線性的。
您可以使用快速選擇算法解釋here以找到一個整數排序的數組的第k最大數量。之後,您可以再次迭代陣列並檢查大於第k個最大元素的元素。所以在兩次迭代中,您可以找到前k個元素。同樣,您可以應用此方法來查找最小的k個元素。
選擇排名算法的時間複雜度是在平均情況下,其中n是陣列中的元素的數目爲O(n)。第二次遍歷數組也需要O(n)次。因此總的複雜性也將是O(n)。
該算法運行速度快於使用堆的方法。因爲使用這種方法時間複雜度將是O(nlogk)。
如果您使用的是Java您可以使用Treemap http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html。
可以對鍵的順序進行排序,並且當遍歷鍵時,可以預期它們將按順序排列。
此時間複雜度是O(n)
建議的算法是什麼? – greybeard
@Claudiu技術上我認爲只有局部排序算法可以通過OP使用。鏈接覆蓋它,但選擇只處理「第k」個最大數量,而不是「top-k」項目。雖然前者可以減少到後者,但我不確定是否可以採用其他方式來放棄複雜性。 – luk32