Saya baru saja mengebom sebuah wawancara dan membuat kemajuan nol pada pertanyaan wawancara saya. Adakah yang bisa memberi tahu saya cara melakukan ini? Saya mencoba mencari secara online tetapi tidak dapat menemukan apa pun:
Diberi nomor, cari angka lebih tinggi berikutnya yang memiliki set digit yang sama persis dengan angka aslinya. Sebagai contoh: diberikan 38.276 pengembalian 38.627
Saya ingin memulai dengan menemukan indeks digit pertama (dari kanan) yang kurang dari digit yang pertama. Lalu saya akan memutar digit terakhir dalam subset sehingga itu adalah angka terbesar berikutnya yang terdiri dari digit yang sama, tetapi macet.
Pewawancara juga menyarankan untuk mencoba menukar angka satu per satu, tetapi saya tidak bisa mengetahui algoritme dan hanya menatap layar selama sekitar 20-30 menit. Tak perlu dikatakan, saya pikir saya harus melanjutkan perburuan pekerjaan.
sunting: berapa nilainya, saya diundang ke putaran wawancara berikutnya
next_permutation
;-)Jawaban:
Anda dapat melakukannya di
O(n)
( di manan
jumlah digit) seperti ini:Mulai dari kanan, Anda menemukan pasangan digit pertama sehingga digit kiri lebih kecil dari digit kanan. Mari merujuk digit kiri dengan "digit-x". Temukan angka terkecil lebih besar dari digit-x di sebelah kanan digit-x, dan letakkan segera di sebelah kiri digit-x. Akhirnya, urutkan digit yang tersisa dalam urutan menaik - karena mereka sudah dalam urutan menurun , yang perlu Anda lakukan adalah membalikkannya (simpan untuk digit-x, yang dapat ditempatkan di tempat yang benar di
O(n)
) .Contoh akan membuat ini lebih jelas:
Bukti kebenaran:
Mari kita gunakan huruf kapital untuk mendefinisikan digit-string dan huruf kecil untuk digit. Sintaks
AB
berarti "rangkaian stringA
danB
" .<
adalah pemesanan leksikografis, yang sama dengan pemesanan integer ketika digit-string memiliki panjang yang sama.Nomor asli N kami adalah dalam bentuk
AxB
, di manax
satu digit danB
diurutkan menurun.Angka yang ditemukan oleh algoritma kami adalah
AyC
, di manay ∈ B
digit terkecil> x
(harus ada karena carax
itu dipilih, lihat di atas) , danC
diurutkan naik.Asumsikan ada beberapa nomor (menggunakan angka yang sama)
N'
sehinggaAxB < N' < AyC
.N'
harus dimulai denganA
atau tidak bisa jatuh di antara mereka, sehingga kita dapat menulisnya di formulirAzD
. Sekarang ketidaksetaraan kami adalahAxB < AzD < AyC
, yang setara dengan dixB < zD < yC
mana ketiga digit-string berisi digit yang sama.Agar hal itu benar, kita harus memilikinya
x <= z <= y
. Karenay
merupakan digit terkecil> x
,z
tidak dapat di antara keduanya, demikian jugaz = x
atauz = y
. Katakanz = x
. Maka ketidaksetaraan kita adalahxB < xD < yC
, yang berarti diB < D
mana keduanyaB
danD
memiliki angka yang sama. Namun, B adalah turun disortir, sehingga ada adalah tidak ada string dengan orang-digit lebih besar dari itu. Dengan demikian kita tidak dapat memilikiB < D
. Mengikuti langkah yang sama, kita melihat bahwa jikaz = y
, kita tidak bisaD < C
.Karenanya
N'
tidak dapat ada, yang berarti algoritme kami dengan benar menemukan angka terbesar berikutnya.sumber
9 832
lalu urutkan semuanya ke kanan 9:9238
Masalah yang hampir identik muncul sebagai masalah Code Jam dan memiliki solusi di sini:
http://code.google.com/codejam/contest/dashboard?c=186264#s=a&a=1
Berikut ringkasan metode menggunakan contoh:
A. Membagi urutan digit menjadi dua, sehingga bagian yang tepat selama mungkin sambil tetap dalam urutan menurun:
(Jika seluruh angka dalam urutan menurun, tidak ada angka yang lebih besar tanpa menambahkan angka.)
B.1. Pilih digit terakhir dari urutan pertama:
B.2. Temukan digit terkecil di urutan kedua yang lebih besar dari itu:
B.3. Tukar mereka:
C. Urutkan urutan kedua ke dalam urutan yang meningkat:
D. Selesai!
sumber
Berikut adalah solusi ringkas (tetapi sebagian kasar) dengan Python
Di C ++ Anda bisa membuat permutasi seperti ini: https://stackoverflow.com/a/9243091/1149664 (Ini algoritma yang sama dengan yang ada di itertools)
Berikut ini adalah implementasi dari jawaban teratas yang dijelaskan oleh Weeble dan BlueRaja, (jawaban lain). Saya ragu ada yang lebih baik.
sumber
type 'map' has no len()
. Saya baru saja mengubah baris ke-2 menjadiiis=list(map(int,str(ii)))
. Dan bisakah ada yang menjelaskanif i == 0: return ii
garisnya? Mengapa ini bekerja dengan input seperti 111 atau 531? Terima kasih.i == len(iis)
.Minimal, berikut adalah beberapa contoh solusi berbasis brute force String, yang seharusnya bisa Anda dapatkan langsung dari atas kepala Anda:
daftar digit dalam
38276
diurutkan adalah23678
daftar digit dalam
38627
diurutkan adalah23678
kenaikan kasar, mengurutkan dan membandingkan
Sepanjang solusi brute force akan dikonversi menjadi String dan brute force semua angka yang mungkin menggunakan angka-angka itu.
Buat int dari semuanya, masukkan ke dalam daftar dan urutkan, dapatkan entri berikutnya setelah entri target.
Jika Anda menghabiskan 30 menit untuk hal ini dan setidaknya tidak datang dengan setidaknya pendekatan kasar, saya juga tidak akan mempekerjakan Anda.
Dalam dunia bisnis, solusi yang tidak elok, lambat dan kikuk tetapi menyelesaikan pekerjaan selalu lebih berharga daripada tidak ada solusi sama sekali, faktanya cukup banyak menggambarkan semua perangkat lunak bisnis, kurang ajar, lambat dan kikuk.
sumber
sumber
Ide kamu
sebenarnya cukup bagus. Anda hanya perlu mempertimbangkan tidak hanya digit terakhir tetapi semua digit kurang penting dari yang saat ini dipertimbangkan. Sejak sebelum itu tercapai, kita memiliki urutan angka monoton, yaitu digit paling kanan lebih kecil dari tetangga kanannya. Menganggap
Angka berikutnya yang lebih besar memiliki angka yang sama
Digit yang ditemukan ditukar dengan digit terakhir - yang terkecil dari digit yang dipertimbangkan - dan digit lainnya diatur dalam urutan yang meningkat.
sumber
Saya cukup yakin pewawancara Anda mencoba mendorong Anda dengan lembut ke arah sesuatu seperti ini:
Tidak harus solusi yang paling efisien atau elegan tetapi memecahkan contoh yang diberikan dalam dua siklus dan bertukar digit satu per satu seperti yang disarankannya.
sumber
Ambil nomor dan pisahkan menjadi angka. Jadi jika kita memiliki nomor 5 digit, kita memiliki 5 digit: abcde
Sekarang tukar d dan e dan bandingkan dengan nomor asli, jika lebih besar, Anda punya jawaban.
Jika tidak lebih besar, tukar e dan c. Sekarang bandingkan dan jika swap lebih kecil d dan e lagi (perhatikan rekursi), ambil yang terkecil.
Lanjutkan sampai Anda menemukan nomor yang lebih besar. Dengan rekursi itu harus bekerja sekitar 9 baris skema, atau 20 c #.
sumber
Itu pertanyaan yang sangat menarik.
Ini adalah versi java saya. Butuh saya sekitar 3 jam dari mencari tahu pola untuk menyelesaikan kode sebelum saya memeriksa komentar kontributor lain. Senang melihat ideku sama dengan orang lain.
O (n) solusi. Jujur, saya akan gagal wawancara ini jika waktunya hanya 15 menit dan memerlukan kode selesai di papan tulis.
Inilah beberapa poin menarik untuk solusi saya:
Saya memberikan komentar detail dalam kode saya, dan Big O di setiap langkah.
Ini adalah hasil yang berjalan di Intellj:
sumber
Implementasi javascript algoritma @ BlueRaja.
sumber
Sebuah solusi (di Jawa) dapat berupa yang berikut ini (saya yakin teman-teman di sini dapat menemukan yang lebih baik):
Mulai bertukar digit dari ujung string hingga Anda mendapatkan angka yang lebih tinggi.
Yaitu pertama mulai bergerak ke atas digit yang lebih rendah. Kemudian yang lebih tinggi berikutnya dll sampai Anda menekan yang lebih tinggi berikutnya.
Kemudian urutkan sisanya. Dalam contoh Anda, Anda akan mendapatkan:
sumber
63872
, apa yang seharusnya?Jika Anda memprogram dalam C ++, Anda bisa menggunakan
next_permutation
:sumber
100
? :-)Saya tidak tahu apa-apa tentang algoritma brute force ketika menjawab pertanyaan ini, jadi saya mendekatinya dari sudut lain. Saya memutuskan untuk mencari seluruh jajaran solusi yang memungkinkan nomor ini dapat diatur ulang, mulai dari number_given +1 hingga jumlah maks yang tersedia (999 untuk angka 3 digit, 9999 untuk 4 digit, dll.). Saya melakukan semacam ini seperti menemukan palindrome dengan kata-kata, dengan mengurutkan angka dari setiap solusi dan membandingkannya dengan nomor yang diurutkan yang diberikan sebagai parameter. Saya kemudian hanya mengembalikan solusi pertama dalam array solusi, karena ini akan menjadi nilai berikutnya yang mungkin.
Ini kode saya di Ruby:
sumber
Kode PHP
sumber
Saya hanya menguji ini dengan dua angka. Mereka bekerja. Sebagai Manajer TI selama 8 tahun hingga pensiun Desember lalu, saya memperhatikan tiga hal: 1) Akurasi: bagus jika berfungsi - selalu. 2) Kecepatan: harus dapat diterima oleh pengguna. 3) Kejelasan: Saya mungkin tidak sepandai Anda, tapi saya membayar Anda. Pastikan Anda menjelaskan apa yang Anda lakukan, dalam bahasa Inggris.
Omar, semoga sukses terus maju.
sumber
Untuk artikel bagus tentang cara melakukan ini, lihat " Algoritma L " di " Seni Pemrograman Komputer " Knuth : Membuat Semua Permutasi "(.ps.gz).
sumber
Ini kode saya, ini adalah versi modifikasi dari contoh ini
Perpustakaan:
Uji:
sumber
Tambahkan 9 ke nomor n digit yang diberikan. Kemudian periksa apakah itu dalam batas (angka digit pertama (n +1)). Jika sudah maka periksa apakah digit dalam nomor baru sama dengan digit pada nomor asli. Ulangi menambahkan 9 hingga kedua kondisinya benar. Hentikan algo ketika jumlahnya melampaui batas.
Saya tidak dapat menemukan kasus uji yang bertentangan untuk metode ini.
sumber
Hanya solusi lain menggunakan python:
Keluaran:
sumber
sumber
Di bawah ini adalah kode untuk menghasilkan semua permutasi dari suatu angka .. meskipun kita harus mengonversi bilangan bulat itu menjadi string menggunakan String.valueOf (integer) terlebih dahulu.
sumber
sumber
Namun implementasi Java lainnya, runnable out of the box dan dilengkapi dengan tes. Solusi ini adalah O (n) ruang dan waktu menggunakan pemrograman dinamis lama yang baik.
Jika seseorang ingin bruteforce, ada 2 jenis bruteforce:
Izinkan semua hal, lalu pilih yang lebih tinggi: O (n!)
Mirip dengan implementasi ini, tetapi bukannya DP, bruteforcing langkah mengisi indeks indexToIndexOfNextSmallerLeft akan berjalan di O (n ^ 2).
sumber
Kita perlu menemukan bit paling tepat 0 diikuti oleh 1 dan balikkan ini paling kanan 0 bit ke 1.
misalnya katakanlah input kami adalah 487, yaitu 111100111 dalam biner.
kami membalik paling kanan 0 yang memiliki 1 mengikutinya
jadi kami mendapatkan 111101111
tetapi sekarang kita memiliki tambahan 1 dan satu kurang 0, jadi kita mengurangi jumlah 1 di sebelah kanan flip bit sebesar 1 dan meningkatkan no 0 bit oleh 1, menghasilkan
111101011 - biner 491
sumber
sumber
Berikut ini adalah Implementasi Java
Inilah Tes Unit
sumber
Saya tahu ini adalah pertanyaan yang sangat lama tetapi saya masih tidak menemukan kode mudah di c #. Ini mungkin membantu orang yang menghadiri wawancara.
sumber
Implementasi yang sangat sederhana menggunakan Javascript, angka tertinggi berikutnya dengan digit yang sama
Karena ada banyak komentar, jadi lebih baik Anda dapat menyalinnya ke editor teks Anda. Terima kasih!
sumber
Ada banyak jawaban bagus tapi saya tidak menemukan implementasi Java yang layak. Ini dua sen saya:
sumber
sumber