Dari komentar saya awalnya: Ini terkait erat dengan kuantitas di mana-mana dalam penilaian produktivitas akademik, indeks Hirsh, lebih dikenal sebagai -indexh . Singkatnya itu didefinisikan sebagai jumlah publikasi satu memiliki rupa sehingga masing-masing dari mereka memiliki setidaknya h kutipan (yang tersebut terbesar h ).hhh
Satu-satunya cara masalah Anda berbeda adalah bahwa Anda akan tertarik tidak hanya pada berapa banyak publikasi yang memenuhi kriteria tetapi juga apa yang dihitung oleh kutipan mereka , tetapi itu adalah modifikasi sepele. Data sudah ada di sana, algoritma asli hanya menjatuhkannya.
Perhitungan yang diterapkan secara umum agak mudah dan setuju dengan jawaban Karolis Juodelė .
Pembaruan: Bergantung pada ukuran dan karakter data Anda, mungkin perlu mengeksplorasi metode yang mengurutkan sebagian array dengan memfilter data di atas dan di bawah titik penting (quicksort muncul di benak). Kemudian tergantung pada apakah ada terlalu sedikit atau terlalu banyak menyesuaikan pivot dan mengulang pada subset yang berisi itu dan seterusnya. Anda tidak perlu urutan antara elemen lebih tinggi dari , dan tentu saja tidak antara yang lebih rendah dari itu. Jadi misalnya, setelah Anda menemukan semua elemen lebih besar atau sama dengan h 1 dan ada kurang dari h 1 dari mereka, Anda tidak perlu menyentuh subset itu lagi, cukup tambahkan saja. Ini mengubah rekursi yang melekat pada quicksort ke rekursi ekor dan dengan demikian dapat ditulis ulang sebagai loop.hh1h1
Haskell saya agak berkarat tetapi ini harus melakukan apa yang saya jelaskan di atas dan tampaknya berhasil. Semoga bisa dipahami sampai taraf tertentu, saya senang bisa memberikan penjelasan lebih lanjut.
-- 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 []
Idenya adalah untuk mengumpulkan granted
apa yang Anda ketahui pasti akan berpartisipasi dalam hasil, dan tidak mengurutkannya lebih jauh. Jika greater
bersama dengan x
kecocokan, kita beruntung, jika tidak kita perlu mencoba dengan subset yang lebih kecil. (Pivot x
adalah apa pun yang kebetulan menjadi item pertama dari sublist yang saat ini dipertimbangkan.) Perhatikan bahwa keuntungan signifikan terhadap pengambilan elemen terbesar satu per satu adalah bahwa kami melakukan ini pada blok ukuran rata-rata dan tidak perlu menyortirnya lebih lanjut.remaining/2
Contoh:
Mari kita ambil set Anda [1,3,4,1,3,6]
.
x = 1
, granted = []
, greater = [3,4,1,3,6]
. Aduh, kita menabrak kasus patologis ketika pivot terlalu kecil (sebenarnya sangat kecil yang smaller
kosong) tepat di langkah pertama. Untungnya algo kami siap untuk itu. Itu membuang x
dan mencoba lagi dengan greater
sendirian.
x = 3
, granted = []
, greater = [4,3,6]
. Bersama-sama, mereka membentuk array dengan panjang 4 tetapi kami hanya memiliki yang terbatas dari bawah dengan 3 jadi itu terlalu banyak. Ulangi greater
sendirian.
x = 4
, granted = []
, greater = [6]
. Ini memberikan array 2 elemen ≥ 4 masing-masing, tampaknya kita mungkin telah menggunakan beberapa elemen lagi. Simpan ini dan ulangi terus smaller = [3]
.
x = 3
, granted = [4,6]
, greater = []
. Ini bersama-sama memberikan array 3 elemen ≥ 3 masing-masing, sehingga kami memiliki solusi kami [3,4,6]
dan kami dapat kembali. (Perhatikan bahwa permutasi dapat bervariasi tergantung pada urutan input, tetapi akan selalu mengandung syarat setinggi mungkin, tidak pernah [3,3,6]
atau [3,3,4]
sebagai contoh Anda.)
(Btw. Perhatikan bahwa rekursi memang hanya runtuh ke satu siklus.) Kompleksitasnya agak lebih baik daripada quicksort karena banyaknya perbandingan yang disimpan:
n−1
O(logn)O(n)
nO(n2)
Ada beberapa perbandingan yang tidak perlu dalam kode di atas, seperti menghitung smaller
apakah kita membutuhkannya atau tidak, mereka dapat dengan mudah dihapus. (Aku pikir evaluasi malas akan membereskannya.)