Saya menemukan sepotong kode yang saya tulis untuk persiapan wawancara beberapa bulan lalu.
Menurut komentar yang saya miliki, itu mencoba menyelesaikan masalah ini:
Diberikan beberapa nilai dolar dalam sen (misalnya 200 = 2 dolar, 1000 = 10 dolar), temukan semua kombinasi koin yang membentuk nilai dolar. Hanya ada uang receh (1 ¢), nikel (5 ¢), dime (10 ¢), dan quarters (25 ¢) yang diperbolehkan.
Misalnya, jika diberikan 100, jawabannya adalah:
4 quarter(s) 0 dime(s) 0 nickel(s) 0 pennies
3 quarter(s) 1 dime(s) 0 nickel(s) 15 pennies
etc.
Saya percaya bahwa ini dapat diselesaikan dengan cara berulang dan rekursif. Solusi rekursif saya cukup bermasalah, dan saya bertanya-tanya bagaimana orang lain akan menyelesaikan masalah ini. Bagian yang sulit dari masalah ini adalah membuatnya seefisien mungkin.
algorithm
recursion
puzzle
coin-change
codingbear
sumber
sumber
code-golf
=> stackoverflow.com/questions/tagged/code-golfJawaban:
Saya melihat ini sekali lama sekali, dan Anda dapat membaca tulisan kecil saya tentangnya . Berikut sumber Mathematica .
Dengan menggunakan fungsi pembangkit, Anda bisa mendapatkan solusi waktu-konstan bentuk-tertutup untuk masalah tersebut. Graham, Knuth, dan Patashnik's Concrete Mathematics adalah buku untuk ini, dan berisi pembahasan masalah yang cukup ekstensif. Pada dasarnya Anda mendefinisikan polinomial di mana koefisien ke- n adalah jumlah cara membuat perubahan untuk n dolar.
Halaman 4-5 dari artikel ini menunjukkan bagaimana Anda dapat menggunakan Mathematica (atau sistem aljabar komputer lain yang nyaman) untuk menghitung jawaban 10 ^ 10 ^ 6 dolar dalam beberapa detik dalam tiga baris kode.
(Dan ini sudah cukup lama sehingga hanya beberapa detik pada Pentium 75Mhz ...)
sumber
a
sebagai domain darif
tapia = {1,5,10,25,50,100}
. Harus ada 5 dalam daftar koin sen. Kalau tidak, tulisannya fantastis, terima kasih!Catatan : Ini hanya menunjukkan beberapa cara.
Fungsi skala:
sumber
n1 * coins(0) + n2 * coins(1) + ... + nN * coins(N-1) = money
. Jadi untukmoney=0
dancoins=List(1,2,5,10)
jumlah kombinasi(n1, n2, n3, n4)
adalah 1 dan solusinya adalah(0, 0, 0, 0)
.money == 0
tetapicoins.isEmpty
, itu tidak dihitung sebagai sol'n. Oleh karena itu, algo mungkin lebih baik disajikan jikacoins.isEmpty || money < 0
kondisinya ditentukan terlebih dahulu.Saya lebih menyukai solusi rekursif. Anda memiliki beberapa daftar denominasi, jika yang terkecil dapat membagi jumlah mata uang yang tersisa secara merata, ini akan berfungsi dengan baik.
Pada dasarnya, Anda berpindah dari denominasi terbesar ke terkecil.
Secara rekursif,
Ini versi python saya dari masalah yang Anda nyatakan, seharga 200 sen. Saya mendapatkan 1463 cara. Versi ini mencetak semua kombinasi dan total hitungan akhir.
sumber
denominations
tidak memiliki1
nilai terakhir. Anda dapat menambahkan sejumlah kecil kode keif
blok terdalam untuk memperbaikinya (seperti yang saya jelaskan dalam jawaban saya untuk pertanyaan lain).Fungsi skala:
sumber
Berikut adalah beberapa kode C ++ yang sangat mudah untuk menyelesaikan masalah yang meminta semua kombinasi untuk ditampilkan.
Tapi saya cukup penasaran tentang sub masalah hanya menghitung jumlah kombinasi. Saya menduga ada persamaan bentuk tertutup untuk itu.
sumber
Sub masalah adalah masalah Pemrograman Dinamis yang khas.
sumber
Kode menggunakan Java untuk menyelesaikan masalah ini dan juga berfungsi ... Metode ini mungkin bukan ide yang baik karena terlalu banyak loop, tetapi ini benar-benar cara yang lurus ke depan.
sumber
Ini adalah pertanyaan yang sangat lama, tapi saya datang dengan solusi rekursif di java yang tampak lebih kecil dari yang lain, jadi begini -
Perbaikan:
sumber
Misalkan C (i, J) himpunan kombinasi pembuatan i sen menggunakan nilai dalam himpunan J.
Anda dapat mendefinisikan C seperti itu:
(pertama (J) dengan cara deterministik mengambil elemen dari suatu himpunan)
Ternyata fungsi yang cukup rekursif ... dan cukup efisien jika Anda menggunakan memoization;)
sumber
semi-hack untuk mengatasi masalah kombinasi unik - paksa urutan menurun:
Ini akan berjalan lambat karena tidak akan dimo, tetapi Anda mengerti.
sumber
sumber
Ini jawaban saya dengan Python. Itu tidak menggunakan rekursi:
Contoh keluaran
sumber
sumber
Keduanya: mengulangi semua denominasi dari tinggi ke rendah, ambil salah satu denominasi, kurangi dari total yang diminta, lalu ulangi sisa (membatasi denominasi yang tersedia menjadi sama atau lebih rendah ke nilai iterasi saat ini.)
sumber
Jika sistem mata uang mengizinkannya, algoritme rakus sederhana yang mengambil sebanyak mungkin setiap koin, dimulai dengan mata uang dengan nilai tertinggi.
Jika tidak, pemrograman dinamis diperlukan untuk menemukan solusi optimal dengan cepat karena masalah ini pada dasarnya adalah masalah ransel .
Misalnya, jika sistem mata uang memiliki koin
{13, 8, 1}
:, solusi serakah akan membuat perubahan untuk 24 as{13, 8, 1, 1, 1}
, tetapi solusi optimal yang sebenarnya adalah{8, 8, 8}
Sunting: Saya pikir kami membuat perubahan secara optimal, tidak mencantumkan semua cara untuk membuat perubahan untuk satu dolar. Wawancara saya baru-baru ini menanyakan bagaimana membuat perubahan jadi saya melompat ke depan sebelum menyelesaikan untuk membaca pertanyaan.
sumber
Saya tahu ini pertanyaan yang sangat lama. Saya sedang mencari jawaban yang tepat dan tidak dapat menemukan apa pun yang sederhana dan memuaskan. Butuh beberapa waktu bagi saya tetapi bisa mencatat sesuatu.
Ini adalah solusi javascript dan menggunakan rekursi.
sumber
Dalam bahasa Pemrograman Scala saya akan melakukannya seperti ini:
sumber
Ini adalah algoritme rekursif sederhana yang mengambil satu tagihan, lalu mengambil tagihan yang lebih kecil secara rekursif hingga mencapai jumlah tersebut, lalu mengambil tagihan lain dengan denominasi yang sama, dan berulang lagi. Lihat contoh keluaran di bawah untuk ilustrasi.
Mencetak yang berikut ini:
sumber
Duh, aku merasa bodoh sekarang. Di bawah ini ada solusi yang terlalu rumit, yang akan saya pertahankan karena itu adalah solusi. Solusi sederhana adalah ini:
Inilah solusi lainnya. Solusi ini didasarkan pada pengamatan bahwa setiap koin adalah kelipatan dari yang lain, sehingga dapat direpresentasikan dalam bentuk koin.
Jadi, untuk 37 koin, misalnya:
sumber
Entri blog saya ini memecahkan masalah seperti ransel untuk tokoh-tokoh dari komik XKCD . Perubahan sederhana pada
items
dict danexactcost
nilainya akan menghasilkan semua solusi untuk masalah Anda juga.Jika masalahnya adalah menemukan perubahan yang menggunakan biaya paling sedikit, maka algoritme rakus naif yang menggunakan koin bernilai tertinggi mungkin gagal untuk beberapa kombinasi koin dan jumlah target. Misalnya jika ada koin dengan nilai 1, 3, dan 4; dan jumlah targetnya adalah 6 maka algoritme rakus mungkin menyarankan tiga koin dengan nilai 4, 1, dan 1 jika mudah untuk melihat bahwa Anda dapat menggunakan dua koin yang masing-masing bernilai 3.
sumber
sumber
Saya menemukan potongan kode yang rapi ini di buku "Python Untuk Analisis Data" oleh O'reily. Ini menggunakan implementasi malas dan perbandingan int dan saya kira itu dapat dimodifikasi untuk denominasi lain menggunakan desimal. Beri tahu saya cara kerjanya untuk Anda!
sumber
Inilah perbaikan dari jawaban Zihan. Banyak putaran yang tidak perlu terjadi jika denominasi hanya 1 sen.
Ini intuitif dan non-rekursif.
sumber
Solusi java langsung:
sumber
sumber
Inilah fungsi C #:
Gunakan seperti ini:
Ini mencetak:
sumber
Di bawah ini adalah program python untuk menemukan semua kombinasi uang. Ini adalah solusi pemrograman dinamis dengan waktu order (n). Uang 1,5,10,25
Kami melintasi dari uang baris 1 ke uang baris 25 (4 baris). Uang baris 1 berisi hitungan jika kita hanya memperhitungkan uang 1 dalam menghitung jumlah kombinasi. Uang baris 5 menghasilkan setiap kolom dengan menghitung uang baris r untuk uang akhir yang sama ditambah 5 hitungan sebelumnya di barisnya sendiri (posisi saat ini dikurangi 5). Uang baris 10 menggunakan uang baris 5, yang berisi hitungan untuk 1,5 dan ditambahkan dalam hitungan 10 sebelumnya (posisi saat ini dikurangi 10). Uang baris 25 menggunakan uang baris 10 yang berisi hitungan uang baris 1,5,10 ditambah 25 hitungan sebelumnya.
Misalnya, angka [1] [12] = angka [0] [12] + angka [1] [7] (7 = 12-5) yang menghasilkan 3 = 1 + 2; angka [3] [12] = angka [2] [12] + angka [3] [9] (-13 = 12-25) yang menghasilkan 4 = 0 + 4, karena -13 kurang dari 0.
sumber
Solusi Java
}
sumber
Solusi java di bawah ini yang akan mencetak kombinasi yang berbeda juga. Mudah dimengerti. Ide adalah
untuk jumlah 5
Solusinya adalah
Jika jumlah yang tersisa di setiap loop lebih kecil dari denominasi yaitu jika jumlah tersisa 1 lebih kecil dari 2, maka putus saja loop
Kode lengkapnya di bawah ini
Harap perbaiki saya jika ada kesalahan
}
sumber
Berikut adalah solusi berbasis python yang menggunakan rekursi serta memoization yang menghasilkan kompleksitas O (mxn)
sumber