Benim yorumum aslen: Bu yakından akademik verimlilik değerlendirmesinde bir miktar yerde ilgilidir, Hirsh indeksi, daha iyi olarak bilinen -İçindekiler . Kısacası, bu yayın sayısı olarak tanımlanır tek her biri en az sahip olduğu şekilde yer alır alıntılar (büyük, örneğin ).hhhh
Sorununuzun farklı olmasının tek yolu, sadece kaç yayının kriteri karşıladığı değil, aynı zamanda atıf sayılarının ne olduğu ile de ilgilenmenizdir , ancak bu önemsiz bir değişikliktir. Veriler zaten orada, orijinal algoritma onu düşürüyor.
Genel olarak uygulanan hesaplama oldukça basittir ve Karolis Juodelė'nin cevabını kabul eder .
Güncelleme: Verilerinizin boyutuna ve karakterine bağlı olarak, verileri önemli bir noktanın üstünde ve altında filtreleyerek diziyi kısmen sıralayan yöntemleri keşfetmeye değer olabilir (quicksort akla gelir). Ardından, çok az veya çok fazla olup olmadığına bağlı olarak, pivotu ayarlayın ve onu içeren alt kümede yeniden yapın vb. Sen daha yüksek elemanları arasında bir sipariş gerekmez değil daha düşük olanlar arasında kesinlikle ve. Örneğin, tüm öğeleri değerine eşit veya daha büyük bulduktan ve bunların değerinden daha azını sonra, bu alt kümeye tekrar dokunmanıza gerek yoktur, sadece ekleyin. Bu, özyinelemenin kendine özgü özyinelemeyi kuyruk özyinelemesine dönüştürür ve böylece bir döngü olarak yeniden yazılabilir.hh1h1
Haskell'im biraz paslı ama bu yukarıda tarif ettiğim şeyi yapmalı ve işe yarıyor gibi görünüyor. Umarım bir dereceye kadar anlaşılabilir, daha fazla açıklama vermekten mutluluk duyuyorum.
-- just a utility function
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : merge xs ys
-- the actual implementation
topImpl :: [Int] -> [Int] -> [Int]
topImpl [] granted = granted
topImpl (x:xs) granted
| x == (1 + lGreater + lGranted) = x : merge greater granted
| x > (1 + lGreater + lGranted) = topImpl smaller (x : merge greater granted)
| otherwise = topImpl greater granted
where smaller = [y | y <- xs, y < x]
greater = [y | y <- xs, y >= x]
lGreater = length greater
lGranted = length granted
-- starting point is: top of whole array, granted is empty
top :: [Int] -> [Int]
top arr = topImpl arr []
Fikir, granted
sonuca kesinlikle katılacağını bildiğiniz şeyleri toplamak ve daha fazla sıralamamaktır. Eğer uyum greater
ile birlikte x
, şanslıyız, aksi takdirde daha küçük bir alt kümeyle denememiz gerekir. (Pivot x
, şu anda dikkate alınan alt listenin ilk öğesi olan şeydir.) En büyük öğeleri teker teker almanın önemli avantajının, bunu ortalama boyutta bloklar üzerinde yapmamız ve ihtiyacımız olmamasıdır. onları sıralamak için.remaining/2
Misal:
Setinizi alalım [1,3,4,1,3,6]
.
x = 1
, granted = []
, greater = [3,4,1,3,6]
. Ah, smaller
ilk adımda pivot çok küçük olduğunda (aslında boş olan çok küçük) patolojik bir duruma çarptık . Neyse ki bizim algo buna hazır. Yalnız atar x
ve tekrar dener greater
.
x = 3
, granted = []
, greater = [4,3,6]
. Birlikte, bir uzunluk 4 dizisi oluştururlar, ancak bunu sadece aşağıdan 3 ile sınırladık, bu yüzden çok fazla. greater
Tek başına tekrarlayın .
x = 4
, granted = []
, greater = [6]
. Bu, her biri elements 4 olmak üzere 2 öğeden oluşan bir dizi verir, daha fazlası için kullanmış olabiliriz. Bunu sakla ve tekrar et smaller = [3]
.
x = 3
, granted = [4,6]
, greater = []
. Bu birlikte her biri 3 elemandan oluşan bir dizi gives 3 verir, böylece çözümümüz vardır [3,4,6]
ve geri dönebiliriz. (Permütasyonun, girişin sırasına bağlı olarak değişebileceğini, ancak asla [3,3,6]
veya [3,3,4]
örneğiniz için daima mümkün olan en yüksek terimleri içereceğini unutmayın.)
(Btw. Özyinelemenin gerçekten de bir döngüye çöktüğünü unutmayın.) Karmaşıklık, birçok kaydedilmiş karşılaştırma nedeniyle hızlı sıralamadan biraz daha iyidir:
En iyi örnek (ör. [2,2,1,1,1,1]): tek bir adım, karşılaştırmaların−1
Ortalama vaka:O(logn)O(n)
nO(n2)
Yukarıdaki kodda smaller
ihtiyaç duyup duymadığımızı hesaplamak gibi birkaç gereksiz karşılaştırma var , bunlar kolayca kaldırılabilir. (Tembel değerlendirmenin bununla ilgileneceğini düşünüyorum.)