Saya memiliki masalah algoritmik.
Diberikan array (atau set) dari bilangan bulat tidak negatif. Temukan set maksimal dari sedemikian rupa sehingga untuk semua ,.
Sebagai contoh:
- Jika = [1, 3, 4, 1, 3, 6], maka dapat menjadi [3, 3, 6] atau [3, 4, 6] atau [4, 3, 6].
- Dalam = [7, 5, 1, 1, 7, 4], maka adalah [7, 5, 7, 4].
Saya sudah mencoba fungsi rekursif ini.
function(T):
if minimum(T) >= length(T):
return T
else:
return function(T\minimum(T))
Apakah ada algoritma non-rekursif. (Saya tidak memeriksa algoritme rekursif saya, sehingga bisa memiliki beberapa kekurangan.)
algorithms
optimization
sets
drzbir
sumber
sumber
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 ).h h h
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.h h1 h1
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.
Idenya adalah untuk mengumpulkanremaining/2
granted
apa yang Anda ketahui pasti akan berpartisipasi dalam hasil, dan tidak mengurutkannya lebih jauh. Jikagreater
bersama denganx
kecocokan, kita beruntung, jika tidak kita perlu mencoba dengan subset yang lebih kecil. (Pivotx
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.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 yangsmaller
kosong) tepat di langkah pertama. Untungnya algo kami siap untuk itu. Itu membuangx
dan mencoba lagi dengangreater
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. Ulangigreater
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 terussmaller = [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:
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.)sumber
Tidak ada yang salah dengan algoritme Anda, dan tentu saja sebagian besar algoritme rekursif dapat dikonversi menjadi loop, di sini versi loop kode rekursif Anda:
sumber
Algoritma rekursif apa pun dapat ditulis ulang untuk menggunakan iterasi. Bagaimanapun, mesin Turing tidak tahu apa-apa tentang rekursi tetapi bisa mengimplementasikan algoritma apa pun. Pada prinsipnya, Anda dapat menulis ulang fungsi rekursif Anda dengan menulis kode manipulasi tumpukan Anda sendiri untuk mengingat nilai-nilai parameter fungsi dan variabel lokal apa pun yang mungkin dimilikinya. Dalam kasus khusus ini, fungsi Anda bersifat ekor-rekursif (sekali panggilan rekursif kembali, hal yang memanggilnya segera kembali juga) sehingga Anda bahkan tidak perlu mempertahankan tumpukan.
sumber
Gunakan min-heap untuk melakukan heapsort parsial, karena Anda tidak perlu seluruh array diurutkan.
Terus popping elemen dengan rakus sampai Anda melebihi ambang yang diberikan.
sumber