Diberi nomor, cari angka lebih tinggi berikutnya yang memiliki set digit yang sama persis dengan angka aslinya


226

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


15
tanpa memikirkannya terlalu awal, paling tidak akan menjadi brute force menghitung semua permutasi digit dan ambil angka minimum yang lebih besar dari jumlah input
BrokenGlass

13
di C ++ Anda bisa menggunakan next_permutation;-)
thedayturns

9
FYI, inilah cara saya menyelesaikannya dalam waktu sekitar 15 menit, bahkan nyaris tidak memikirkan masalah: pertama-tama saya menghabiskan 5 menit untuk menulis algoritma brute-force yang baru saja menciptakan semua permutasi yang mungkin dari satu set digit, mengurutkannya, dan menampilkannya. Aku menghabiskan 5 menit melihat melalui bahwa data sampai pola muncul dari daftar (O (n) menerima solusi di sini menjadi jelas setelah hanya dalam waktu singkat mencari), maka saya menghabiskan 5 menit coding O (n) algoritma.
Ben Lee

1
Secara umum, ini bukan cara yang buruk untuk menghasilkan algoritma untuk menyelesaikan masalah seperti ini saat Anda macet - gunakan brute force pada beberapa sampel berukuran kecil untuk membuat banyak data yang kemudian dapat Anda gunakan untuk melihat pola dengan lebih mudah.
Ben Lee

19
Saya juga ingin menunjukkan, jika Anda benar - benar tidak dapat menemukan cara yang efisien untuk melakukan ini, tidak melakukan apa pun adalah cara yang pasti untuk gagal dalam wawancara (dan di dunia bisnis, ini adalah cara yang pasti untuk melewatkan tenggat waktu produk) . Ketika Anda terjebak, alih-alih menyerah, Anda seharusnya memaksanya dengan kasar dan memberikan komentar di bagian atas "TODO: refactor for performance" atau sesuatu seperti itu. Jika saya mewawancarai dan seseorang melakukannya, saya tidak akan mengecewakan mereka. Setidaknya mereka datang dengan sesuatu yang berhasil DAN menyadari bahwa ada sesuatu yang lebih baik di luar sana, bahkan jika mereka tidak dapat menemukannya.
Ben Lee

Jawaban:


272

Anda dapat melakukannya di O(n)( di mana njumlah 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:

123456784987654321
mulai dengan angka

123456784 987654321
         ^ tempat pertama dari kanan di mana digit kiri kurang dari kanan  
         Digit "x" adalah 4

123456784 987654321
              ^ temukan digit terkecil lebih besar dari 4 ke kanan

123456785 4 98764321
        ^ letakkan di sebelah kiri 4

123456785 4 12346789
123456785123446789
         ^ urutkan digit ke kanan 5. Karena semuanya kecuali 
         '4' sudah dalam urutan menurun, yang perlu kita lakukan adalah 
         membalikkan pesanan mereka, dan menemukan tempat yang tepat untuk '4'

Bukti kebenaran:

Mari kita gunakan huruf kapital untuk mendefinisikan digit-string dan huruf kecil untuk digit. Sintaks ABberarti "rangkaian string Adan B" . <adalah pemesanan leksikografis, yang sama dengan pemesanan integer ketika digit-string memiliki panjang yang sama.

Nomor asli N kami adalah dalam bentuk AxB, di mana xsatu digit dan Bdiurutkan menurun.
Angka yang ditemukan oleh algoritma kami adalah AyC, di mana y ∈ Bdigit terkecil > x (harus ada karena cara xitu dipilih, lihat di atas) , dan Cdiurutkan naik.

Asumsikan ada beberapa nomor (menggunakan angka yang sama) N'sehingga AxB < N' < AyC. N'harus dimulai dengan Aatau tidak bisa jatuh di antara mereka, sehingga kita dapat menulisnya di formulir AzD. Sekarang ketidaksetaraan kami adalah AxB < AzD < AyC, yang setara dengan di xB < zD < yCmana ketiga digit-string berisi digit yang sama.

Agar hal itu benar, kita harus memilikinya x <= z <= y. Karena ymerupakan digit terkecil > x, ztidak dapat di antara keduanya, demikian juga z = xatau z = y. Katakan z = x. Maka ketidaksetaraan kita adalah xB < xD < yC, yang berarti di B < Dmana keduanya Bdan Dmemiliki 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 memiliki B < D. Mengikuti langkah yang sama, kita melihat bahwa jika z = y, kita tidak bisa D < C.

Karenanya N'tidak dapat ada, yang berarti algoritme kami dengan benar menemukan angka terbesar berikutnya.


7
solusi bagus! punya satu pertanyaan. katakan "digit terkecil yang lebih besar dari x" adalah y. bisakah kita menukar x dan y, lalu membalikkan x.index + 1 -> end?
Kent

8
Apa yang terjadi pada nomor 99999?
Sterex

19
@Terex, ini bukan hanya 99999; angka berapa pun yang digitnya sudah sepenuhnya diurutkan dalam urutan menurun adalah maks (jadi 98765 juga tidak memiliki solusi, misalnya). Ini mudah dideteksi secara programatik karena langkah 1 dari algoritme akan gagal (tidak ada pasangan digit yang berurutan sehingga "digit kiri lebih kecil daripada digit kanan").
Ben Lee

3
@TMN: 9 lebih besar dari 8, jadi Anda akan memindahkan 9 ke kiri 8: 9 832lalu urutkan semuanya ke kanan 9:9238
BlueRaja - Danny Pflughoeft

4
@Kirim agar solusi Anda berfungsi, Anda harus mengubah menemukan digit terkecil lebih besar dari 4 ke kanan untuk menemukan digit terkecil lebih besar dari 4 dari kanan . Kalau tidak, misalnya, 1234567849876 55 4321 akan menghasilkan 1234567851234 54 6789 (bukan 1234567851234 45 6789). A nitpick :-)
osundblad

94

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:

34722641

A. Membagi urutan digit menjadi dua, sehingga bagian yang tepat selama mungkin sambil tetap dalam urutan menurun:

34722 641

(Jika seluruh angka dalam urutan menurun, tidak ada angka yang lebih besar tanpa menambahkan angka.)

B.1. Pilih digit terakhir dari urutan pertama:

3472(2) 641

B.2. Temukan digit terkecil di urutan kedua yang lebih besar dari itu:

3472(2) 6(4)1

B.3. Tukar mereka:

3472(2) 6(4)1
->
3472(4) 6(2)1
->
34724 621

C. Urutkan urutan kedua ke dalam urutan yang meningkat:

34724 126

D. Selesai!

34724126

1
Ketikan di sana: Saya pikir "-> 34721 621" harus "-> 34724 621"?
bjnord

1
@ bjnord Tangkapan bagus. Tetap. Tidak yakin bagaimana saya mengaturnya - itu benar di baris berikutnya.
Weeble

+1 Jawaban terbaik di sini. Intuitif dan cepat. (Itu juga yang saya pikirkan ketika saya mengerjakan ini di atas kertas;))
Muhd

1
@Neel - Pada langkah C, angka yang ingin kami urutkan berada dalam urutan menurun, kecuali untuk digit yang kami tukar di langkah B. Untuk mengurutkannya, kami hanya perlu membalikkannya dan memasukkan digit yang ditukar ke posisi yang tepat. Inilah yang dijelaskan BlueRaja.
Weeble

1
@ Davidavave Apa masalahnya? Pada langkah A Anda mendapatkan "12" dan "3". Pada langkah B Anda mendapatkan "13" dan "2". Pada langkah C tidak ada yang berubah. Pada langkah D Anda mendapatkan "132". Satu-satunya kasus di mana Anda tidak akan mendapatkan jawaban adalah ketika angkanya sudah semaksimal mungkin, misalnya "321". Dalam hal ini, langkah A memberi Anda "" dan "321", dan Anda tidak dapat melanjutkan dengan urutan kosong untuk sisi kiri perpecahan.
Weeble

14

Berikut adalah solusi ringkas (tetapi sebagian kasar) dengan Python

def findnext(ii): return min(v for v in (int("".join(x)) for x in
    itertools.permutations(str(ii))) if v>ii)

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.

def findnext(ii):
    iis=list(map(int,str(ii)))
    for i in reversed(range(len(iis))):
        if i == 0: return ii
        if iis[i] > iis[i-1] :
            break        
    left,right=iis[:i],iis[i:]
    for k in reversed(range(len(right))):
        if right[k]>left[-1]:
           right[k],left[-1]=left[-1],right[k]
           break
    return int("".join(map(str,(left+sorted(right)))))

Adakah peluang bagi siapa saja untuk memperbarui ini? Tampaknya tidak berfungsi di Python 3 seperti yang ditunjukkan type 'map' has no len(). Saya baru saja mengubah baris ke-2 menjadi iis=list(map(int,str(ii))). Dan bisakah ada yang menjelaskan if i == 0: return iigarisnya? Mengapa ini bekerja dengan input seperti 111 atau 531? Terima kasih.
Bowen Liu

Saya memperbaikinya untuk python 3 sekarang dengan menambahkan ´list () ke iis = ... ´. Kasus 111 dan 531 tidak memiliki solusi tetapi implementasi saya mengembalikan 111 dan 531 untuk itu. Anda bisa mengubahnya menjadi pengecualian dari apa yang Anda temukan lebih baik dengan mengubah baris i == 0.
Johan Lundberg

Terima kasih. Saya benar-benar berputar ke arah lain jadi saya bingung dengan i == 0, sementara dalam situasi saya akan menjadi i == len(iis).
Bowen Liu

8

Minimal, berikut adalah beberapa contoh solusi berbasis brute force String, yang seharusnya bisa Anda dapatkan langsung dari atas kepala Anda:

daftar digit dalam 38276diurutkan adalah23678

daftar digit dalam 38627diurutkan 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.


1
Yah komentar pertama saya dari kelelawar adalah "Saya bisa dengan kasar memaksanya tapi ...". Jika benar-benar bukan solusi algoritmik, aku agak kecewa
bhan

4
Jika saya pewawancara, saya tidak akan senang dengan pendekatan brute force.
Ahmad Y. Saleh

@ Benjamin han, ada solusi algoritmik. Tetap pertukarkan angka mulai dari kanan, hingga Anda menemukan hasilnya. Tidak perlu menghitung semua permutatnios sebelumnya.
dantuch

7
Tentunya ada solusi yang jauh lebih baik daripada brute force, misalnya ardendertat.com/2012/01/02/…
BrokenGlass

@ BrokenGlass Pasti solusi yang jauh lebih baik. Saya baru saja datang dengan ide itu dan kemudian Anda memposting algoritma.
onit

5
function foo(num){
 sortOld = num.toString().split("").sort().join('');
 do{
    num++;
   sortNew = num.toString().split("").sort().join('');
 }while(sortNew!==sortOld);
 return num;
}

Saya datang dengan solusi ini. Silakan jika Anda memiliki pertanyaan, tanyakan.
Ashikodi

4

Ide kamu

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.

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

1234675
    ^

Angka berikutnya yang lebih besar memiliki angka yang sama

1234756

Digit yang ditemukan ditukar dengan digit terakhir - yang terkecil dari digit yang dipertimbangkan - dan digit lainnya diatur dalam urutan yang meningkat.


4

Saya cukup yakin pewawancara Anda mencoba mendorong Anda dengan lembut ke arah sesuatu seperti ini:

local number = 564321;

function split(str)
    local t = {};
    for i = 1, string.len(str) do
        table.insert(t, str.sub(str,i,i));
    end
    return t;
end

local res = number;
local i = 1;
while number >= res do
    local t = split(tostring(res));
    if i == 1 then
        i = #t;
    end
    t[i], t[i-1] = t[i-1], t[i];
    i = i - 1;
    res = tonumber(table.concat(t));
end

print(res);

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.


2

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 #.


2

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:

  • Hindari penyortiran.
  • Hindari operasi string sepenuhnya
  • Mencapai kompleksitas ruang O (logN)

Saya memberikan komentar detail dalam kode saya, dan Big O di setiap langkah.

  public int findNextBiggestNumber(int input  )   {
    //take 1358642 as input for example.
    //Step 1: split the whole number to a list for individual digital   1358642->[2,4,6,8,5,3,1]
    // this step is O(n)
    int digitalLevel=input;

    List<Integer> orgNumbersList=new ArrayList<Integer>()   ;

    do {
        Integer nInt = new Integer(digitalLevel % 10);
        orgNumbersList.add(nInt);

        digitalLevel=(int) (digitalLevel/10  )  ;


    } while( digitalLevel >0)    ;
    int len= orgNumbersList.size();
    int [] orgNumbers=new int[len]  ;
    for(int i=0;i<len;i++){
        orgNumbers[i ]  =  orgNumbersList.get(i).intValue();
    }
    //step 2 find the first digital less than the digital right to it
    // this step is O(n)


    int firstLessPointer=1;
    while(firstLessPointer<len&&(orgNumbers[firstLessPointer]>orgNumbers[ firstLessPointer-1 ])){
        firstLessPointer++;
    }
     if(firstLessPointer==len-1&&orgNumbers[len-1]>=orgNumbers[len-2]){
         //all number is in sorted order like 4321, no answer for it, return original
         return input;
     }

    //when step 2 step finished, firstLessPointer  pointing to number 5

     //step 3 fristLessPointer found, need to find  to  first number less than it  from low digital in the number
    //This step is O(n)
    int justBiggerPointer=  0 ;

    while(justBiggerPointer<firstLessPointer&& orgNumbers[justBiggerPointer]<orgNumbers[firstLessPointer]){
        justBiggerPointer++;
    }
    //when step 3 finished, justBiggerPointer  pointing to 6

    //step 4 swap the elements  of justBiggerPointer and firstLessPointer .
    // This  is O(1) operation   for swap

   int tmp=  orgNumbers[firstLessPointer] ;

    orgNumbers[firstLessPointer]=  orgNumbers[justBiggerPointer]  ;
     orgNumbers[justBiggerPointer]=tmp ;


     // when step 4 finished, the list looks like        [2,4,5,8,6,3,1]    the digital in the list before
     // firstLessPointer is already sorted in our previous operation
     // we can return result from this list  but  in a differrent way
    int result=0;
    int i=0;
    int lowPointer=firstLessPointer;
    //the following pick number from list from  the position just before firstLessPointer, here is 8 -> 5 -> 4 -> 2
    //This Operation is O(n)
    while(lowPointer>0)        {
        result+= orgNumbers[--lowPointer]* Math.pow(10,i);
        i++;
    }
    //the following pick number from list   from position firstLessPointer
    //This Operation is O(n)
    while(firstLessPointer<len)        {
        result+= orgNumbers[firstLessPointer++ ]* Math.pow(10,i);
        i++;
    }
     return  result;

}

Ini adalah hasil yang berjalan di Intellj:

959879532-->959892357
1358642-->1362458
1234567-->1234576
77654321-->77654321
38276-->38627
47-->74

dalam hal 123 apa yang akan dijawab? Secara praktis, Anda akan kode tidak akan menghasilkan output saat itu datang 132
Dhaval dave

2

Implementasi javascript algoritma @ BlueRaja.

var Bar = function(num){ 
  num = num.toString();
  var max = 0;
  for(var i=num.length-2; i>0; i--){
    var numArray = num.substr(i).split("");
    max = Math.max.apply(Math,numArray);
    if(numArray[0]<max){
        numArray.sort(function(a,b){return a-b;});
        numArray.splice(-1);
        numArray = numArray.join("");
        return Number(num.substr(0,i)+max+numArray);
    }
  }
  return -1;
};

1

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:

38276 --> 38267 (smaller) --> 38627 Found it    
    ^        ^                  ^        

 public static int nextDigit(int number){
    String num = String.valueOf(number);        
    int stop = 0;       
    char [] chars = null;
    outer:
        for(int i = num.length() - 1; i > 0; i--){          
            chars = num.toCharArray();
            for(int j = i; j > 0; j--){
                char temp = chars[j];
                chars[j] = chars[j - 1];
                chars[j - 1] = temp;
                if(Integer.valueOf(new String(chars)) > number){
                    stop = j;                   
                    break outer;                                
                }               
            }               
        }

    Arrays.sort(chars, stop, chars.length); 
    return Integer.valueOf(new String(chars));
}

@yi_H: Outputnya. Kenapa 63872, apa yang seharusnya?
Cratylus

baik .. angka selanjutnya yang lebih tinggi? :) itu persyaratannya, bukan?
Karoly Horvath

@BlueRaja - Danny Pflughoeft: Terima kasih atas bantuan Anda. Saya mengubah kode sebagai berikut: Pindahkan digit terkecil di muka (yang pernah menghasilkan angka lebih tinggi) dan urutkan sisanya
Cratylus

1

Jika Anda memprogram dalam C ++, Anda bisa menggunakan next_permutation:

#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, char **argv) {
  using namespace std; 
   string x;
   while (cin >> x) {
    cout << x << " -> ";
    next_permutation(x.begin(),x.end());
    cout << x << "\n";
  }
  return 0;
}

Apa yang terjadi jika saya masukan 100? :-)
jweyrich

1

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:

def PermutationStep(num)

    a = []
    (num.to_s.length).times { a.push("9") }
    max_num = a.join('').to_i
    verify = num.to_s.split('').sort
    matches = ((num+1)..max_num).select {|n| n.to_s.split('').sort == verify }

    if matches.length < 1
      return -1
    else
      matches[0]
    end
end

apa kompleksitas waktu dari solusi ini?
Nitish Upreti

@ Myth17 Saya tidak yakin, karena saya tidak pernah mengujinya. Jika Anda ingin mengetahuinya, periksa pos ini: stackoverflow.com/questions/9958299/…
Jeremiah McCurdy

1

Kode PHP

function NextHigherNumber($num1){
$num = strval($num1);
$max = 0;
for($i=(strlen($num)-2); $i>=0; $i--){
    $numArrayRaw = substr($num, $i);
    $numArray = str_split($numArrayRaw);
    $max = max($numArray);
    if ($numArray[0] < $max){
        sort( $numArray, SORT_NUMERIC );
        array_pop($numArray);
        $numarrstr = implode("",$numArray);
        $rt = substr($num,0,$i) . $max . $numarrstr;
        return $rt;
    }
}
return "-1";
}
echo NextHigherNumber(123);

0

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.

Sub Main()

Dim Base(0 To 9) As Long
Dim Test(0 To 9) As Long

Dim i As Long
Dim j As Long
Dim k As Long
Dim ctr As Long

Const x As Long = 776914648
Dim y As Long
Dim z As Long

Dim flag As Boolean

' Store the digit count for the original number in the Base vector.
    For i = 0 To 9
        ctr = 0
        For j = 1 To Len(CStr(x))
            If Mid$(CStr(x), j, 1) = i Then ctr = ctr + 1
        Next j
        Base(i) = ctr
    Next i

' Start comparing from the next highest number.
    y = x + 1
    Do

' Store the digit count for the each new number in the Test vector.
        flag = False
        For i = 0 To 9
            ctr = 0
            For j = 1 To Len(CStr(y))
                If Mid$(CStr(y), j, 1) = i Then ctr = ctr + 1
            Next j
            Test(i) = ctr
        Next i

' Compare the digit counts.
        For k = 0 To 9
            If Test(k) <> Base(k) Then flag = True
        Next k

' If no match, INC and repeat.
        If flag = True Then
            y = y + 1
            Erase Test()
        Else
            z = y ' Match.
        End If

    Loop Until z > 0

    MsgBox (z), , "Solution"

End Sub


0

Ini kode saya, ini adalah versi modifikasi dari contoh ini

Perpustakaan:

class NumPermExample
{
    // print N! permutation of the characters of the string s (in order)
    public  static void perm1(String s, ArrayList<String> perm)
    {
        perm1("", s);
    }

    private static void perm1(String prefix, String s, ArrayList<String> perm)
    {
        int N = s.length();
        if (N == 0)
        {
            System.out.println(prefix);
            perm.add(prefix);
        }
        else
        {
            for (int i = 0; i < N; i++)
                perm1(prefix + s.charAt(i), s.substring(0, i)
                    + s.substring(i+1, N));
        }

    }

    // print N! permutation of the elements of array a (not in order)
    public static void perm2(String s, ArrayList<String> perm)
    {
       int N = s.length();
       char[] a = new char[N];
       for (int i = 0; i < N; i++)
           a[i] = s.charAt(i);
       perm2(a, N);
    }

    private static void perm2(char[] a, int n, ArrayList<String> perm)
    {
        if (n == 1)
        {
            System.out.println(a);
            perm.add(new String(a));
            return;
        }

        for (int i = 0; i < n; i++)
        {
            swap(a, i, n-1);
            perm2(a, n-1);
            swap(a, i, n-1);
        }
    }  

    // swap the characters at indices i and j
    private static void swap(char[] a, int i, int j)
    {
        char c;
        c = a[i]; a[i] = a[j]; a[j] = c;
    }

    // next higher permutation
    public static int nextPermutation (int number)
    {
        ArrayList<String> perm = new ArrayList<String>();

        String cur = ""+number;

        int nextPerm = 0;

        perm1(cur, perm);

        for (String s : perm)
        {
            if (Integer.parseInt(s) > number
                        && (nextPerm == 0 ||
                            Integer.parseInt(s) < nextPerm))
            {
                nextPerm = Integer.parseInt(s);
            }
        }

            return nextPerm;
    }
}

Uji:

public static void main(String[] args) 
{
    int a = 38276;

    int b = NumPermExample.nextPermutation(a);

    System.out.println("a: "+a+", b: "+b);
}

0

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.


1
Ini bekerja, tetapi sangat lambat. Ini adalah algoritma waktu eksponensial di mana ini dapat diselesaikan dalam waktu linier.
interjay

0

Hanya solusi lain menggunakan python:

def PermutationStep(num):
    if sorted(list(str(num)), reverse=True) == list(str(num)):
        return -1
    ls = list(str(num))
    n = 0
    inx = 0
    for ind, i in enumerate(ls[::-1]):
        if i < n:
            n = i
            inx = -(ind + 1)
            break
        n = i
    ls[inx], ls[inx + 1] = ls[inx + 1], ls[inx]

    nl = ls[inx::-1][::-1]
    ln = sorted(ls[inx+1:])
    return ''.join(nl) + ''.join(ln)

print PermutationStep(23514)

Keluaran:

23541

0
public static void findNext(long number){

        /* convert long to string builder */    

        StringBuilder s = new StringBuilder();
        s.append(number);
        int N = s.length();
        int index=-1,pivot=-1;

/* from tens position find the number (called pivot) less than the number in right */ 

        for(int i=N-2;i>=0;i--){

             int a = s.charAt(i)-'0';
             int b = s.charAt(i+1)-'0';

             if(a<b){
                pivot = a;
                index =i;
                break;
            }
        }

      /* if no such pivot then no solution */   

        if(pivot==-1) System.out.println(" No such number ")

        else{   

     /* find the minimum highest number to the right higher than the pivot */

            int nextHighest=Integer.MAX_VALUE, swapIndex=-1;

            for(int i=index+1;i<N;i++){

            int a = s.charAt(i)-'0';

            if(a>pivot && a<nextHighest){
                    nextHighest = a;
                    swapIndex=i;
                }
            }


     /* swap the pivot and next highest number */

            s.replace(index,index+1,""+nextHighest);
            s.replace(swapIndex,swapIndex+1,""+pivot);

/* sort everything to right of pivot and replace the sorted answer to right of pivot */

            char [] sort = s.substring(index+1).toCharArray();
            Arrays.sort(sort);

            s.replace(index+1,N,String.copyValueOf(sort));

            System.out.println("next highest number is "+s);
        }

    }

0

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.

/**
 * 
 * Inserts a integer at any index around string.
 * 
 * @param number
 * @param position
 * @param item
 * @return
 */
public String insertToNumberStringAtPosition(String number, int position,
        int item) {
    String temp = null;
    if (position >= number.length()) {
        temp = number + item;
    } else {
        temp = number.substring(0, position) + item
                + number.substring(position, number.length());
    }
    return temp;
}

/**
 * To generate permutations of a number.
 * 
 * @param number
 * @return
 */
public List<String> permuteNumber(String number) {
    List<String> permutations = new ArrayList<String>();
    if (number.length() == 1) {
        permutations.add(number);
        return permutations;
    }
    // else
    int inserterDig = (int) (number.charAt(0) - '0');
    Iterator<String> iterator = permuteNumber(number.substring(1))
            .iterator();
    while (iterator.hasNext()) {
        String subPerm = iterator.next();
        for (int dig = 0; dig <= subPerm.length(); dig++) {
            permutations.add(insertToNumberStringAtPosition(subPerm, dig,
                    inserterDig));
        }
    }
    return permutations;
}

0
#include<bits/stdc++.h>
using namespace std;
int main() 
{
    int i,j,k,min,len,diff,z,u=0,f=0,flag=0;
    char temp[100],a[100]`enter code here`,n;
    min=9999;
    //cout<<"Enter the number\n";
    cin>>a;
    len=strlen(a);
    for(i=0;i<len;i++)
    {
        if(a[i]<a[i+1]){flag=1;break;}
    }
    if(flag==0){cout<<a<<endl;}
    else
    {
        for(i=len-1;i>=0;i--)if(((int)a[i-1])<((int)a[i]))break;
        for(k=0;k<i-1;k++)cout<<a[k];
        for(j=i;j<len;j++)
        {
            if(((int)a[j]-48)-((int)a[i-1]-48)>0)
            {
                diff=((int)a[j]-48)-((int)a[i-1]-48);
                if(diff<min){n=a[j];min=diff;}
            }
        }
        cout<<n;
        for(z=i-1;z<len;z++)
        {
            temp[u]=a[z];
            u++;
        }
        temp[u]='\0';
        sort(temp,temp+strlen(temp));
        for(z=0;z<strlen(temp);z++){if(temp[z]==n&&f==0){f=1;continue;}cout<<temp[z];}
    }
    return 0;
}

0

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:

  1. Izinkan semua hal, lalu pilih yang lebih tinggi: O (n!)

  2. Mirip dengan implementasi ini, tetapi bukannya DP, bruteforcing langkah mengisi indeks indexToIndexOfNextSmallerLeft akan berjalan di O (n ^ 2).


import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class NextHigherSameDigits {

    public long next(final long num) {
        final char[] chars = String.valueOf(num).toCharArray();
        final int[] digits = new int[chars.length];
        for (int i = 0; i < chars.length; i++) {
            digits[i] = Character.getNumericValue(chars[i]);
        }

        final Map<Integer, Integer> indexToIndexOfNextSmallerLeft = new HashMap<>();
        indexToIndexOfNextSmallerLeft.put(1, digits[1] > digits[0] ? 0 : null);
        for (int i = 2; i < digits.length; i++) {
            final int left = digits[i - 1];
            final int current = digits[i];
            Integer indexOfNextSmallerLeft = null;
            if (current > left) {
                indexOfNextSmallerLeft = i - 1;
            } else {
                final Integer indexOfnextSmallerLeftOfLeft = indexToIndexOfNextSmallerLeft.get(i - 1);
                final Integer nextSmallerLeftOfLeft = indexOfnextSmallerLeftOfLeft == null ? null : 
                    digits[indexOfnextSmallerLeftOfLeft];

                if (nextSmallerLeftOfLeft != null && current > nextSmallerLeftOfLeft) {
                    indexOfNextSmallerLeft = indexOfnextSmallerLeftOfLeft;
                } else {
                    indexOfNextSmallerLeft = null;
                }
            }

            indexToIndexOfNextSmallerLeft.put(i, indexOfNextSmallerLeft);
        }

        Integer maxOfindexOfNextSmallerLeft = null;
        Integer indexOfMinToSwapWithNextSmallerLeft = null;
        for (int i = digits.length - 1; i >= 1; i--) {
            final Integer indexOfNextSmallerLeft = indexToIndexOfNextSmallerLeft.get(i);
            if (maxOfindexOfNextSmallerLeft == null ||
                    (indexOfNextSmallerLeft != null && indexOfNextSmallerLeft > maxOfindexOfNextSmallerLeft)) {

                maxOfindexOfNextSmallerLeft = indexOfNextSmallerLeft;
                if (maxOfindexOfNextSmallerLeft != null && (indexOfMinToSwapWithNextSmallerLeft == null || 
                        digits[i] < digits[indexOfMinToSwapWithNextSmallerLeft])) {

                    indexOfMinToSwapWithNextSmallerLeft = i;
                }
            }
        }

        if (maxOfindexOfNextSmallerLeft == null) {
            return -1;
        } else {
            swap(digits, indexOfMinToSwapWithNextSmallerLeft, maxOfindexOfNextSmallerLeft);
            reverseRemainingOfArray(digits, maxOfindexOfNextSmallerLeft + 1);
            return backToLong(digits);
        }
    }

    private void reverseRemainingOfArray(final int[] digits, final int startIndex) {
        final int[] tail = Arrays.copyOfRange(digits, startIndex, digits.length);
        for (int i = tail.length - 1; i >= 0; i--) {
            digits[(digits.length - 1)  - i] = tail[i];                 
        }
    }

    private void swap(final int[] digits, final int currentIndex, final int indexOfNextSmallerLeft) {
        int temp = digits[currentIndex];
        digits[currentIndex] = digits[indexOfNextSmallerLeft];
        digits[indexOfNextSmallerLeft] = temp;
    }

    private long backToLong(int[] digits) {     
        StringBuilder sb = new StringBuilder();
        for (long i : digits) {
            sb.append(String.valueOf(i));
        }

        return Long.parseLong(sb.toString());
    }

    @Test
    public void test() {
        final long input1 =    34722641;
        final long expected1 = 34724126;
        final long output1 = new NextHigherSameDigits().next(input1);
        assertEquals(expected1, output1);

        final long input2 =    38276;
        final long expected2 = 38627;
        final long output2 = new NextHigherSameDigits().next(input2);
        assertEquals(expected2, output2);

        final long input3 =    54321;
        final long expected3 = -1;
        final long output3 = new NextHigherSameDigits().next(input3);
        assertEquals(expected3, output3);

        final long input4 =    123456784987654321L;
        final long expected4 = 123456785123446789L;
        final long output4 = new NextHigherSameDigits().next(input4);
        assertEquals(expected4, output4);

        final long input5 =    9999;
        final long expected5 = -1;
        final long output5 = new NextHigherSameDigits().next(input5);
        assertEquals(expected5, output5);
    }

}

0

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

int getNextNumber(int input)
{
    int flipPosition=0;
    int trailingZeros=0;
    int trailingOnes=0;
    int copy = input;

    //count trailing zeros
    while(copy != 0 && (copy&1) == 0 )
    {
        ++trailingZeros;

        //test next bit
        copy = copy >> 1;
    }

    //count trailing ones
    while(copy != 0 && (copy&1) == 1 )
    {
        ++trailingOnes;

        //test next bit
        copy = copy >> 1;
    }

    //if we have no 1's (i.e input is 0) we cannot form another pattern with 
    //the same number of 1's which will increment the input, or if we have leading consecutive
    //ones followed by consecutive 0's up to the maximum bit size of a int
    //we cannot increase the input whilst preserving the original no of 0's and
    //1's in the bit pattern
    if(trailingZeros + trailingOnes  == 0 || trailingZeros + trailingOnes == 31)
        return -1;

    //flip first 0 followed by a 1 found from the right of the bit pattern
    flipPosition = trailingZeros + trailingOnes+1;
    input |= 1<<(trailingZeros+trailingOnes);

    //clear fields to the right of the flip position
    int mask = ~0 << (trailingZeros+trailingOnes);
    input &= mask;

    //insert a bit pattern to the right of the flip position that will contain
    //one less 1 to compensate for the bit we switched from 0 to 1
    int insert = flipPosition-1;
    input |= insert;

    return input;
}

0
int t,k,num3,num5;
scanf("%d",&t);
int num[t];
for(int i=0;i<t;i++){
    scanf("%d",&num[i]);   
}
for(int i=0;i<t;i++){
    k=(((num[i]-1)/3)+1); 
    if(k<0)
        printf("-1");
    else if(num[i]<3 || num[i]==4 || num[i]==7)
        printf("-1");
    else{
        num3=3*(2*num[i] - 5*k);
        num5=5*(3*k -num[i]);
        for(int j=0;j<num3;j++)
            printf("5");
        for(int j=0;j<num5;j++)
            printf("3");
    }
    printf("\n");
}

0

Berikut ini adalah Implementasi Java

public static int nextHigherNumber(int number) {
    Integer[] array = convertToArray(number);
    int pivotIndex = pivotMaxIndex(array);
    int digitInFirstSequence = pivotIndex -1;
    int lowerDigitIndexInSecondSequence = lowerDigitIndex(array[digitInFirstSequence], array, pivotIndex);
    swap(array, digitInFirstSequence, lowerDigitIndexInSecondSequence);
    doRercursiveQuickSort(array, pivotIndex, array.length - 1);
    return arrayToInteger(array);
}

public static Integer[] convertToArray(int number) {
    int i = 0;
    int length = (int) Math.log10(number);
    int divisor = (int) Math.pow(10, length);
    Integer temp[] = new Integer[length + 1];

    while (number != 0) {
        temp[i] = number / divisor;
        if (i < length) {
            ++i;
        }
        number = number % divisor;
        if (i != 0) {
            divisor = divisor / 10;
        }
    }
    return temp;
}

private static int pivotMaxIndex(Integer[] array) {
    int index = array.length - 1;
    while(index > 0) {
        if (array[index-1] < array[index]) {
            break;
        }
        index--;
    }       
    return index;
}

private static int lowerDigitIndex(int number, Integer[] array, int fromIndex) {
    int lowerMaxIndex = fromIndex;
    int lowerMax = array[lowerMaxIndex];
    while (fromIndex < array.length - 1) {
        if (array[fromIndex]> number && lowerMax > array[fromIndex]) {
            lowerMaxIndex = fromIndex; 
        }
        fromIndex ++;
    }
    return lowerMaxIndex;
}

public static int arrayToInteger(Integer[] array) {
    int number = 0;
    for (int i = 0; i < array.length; i++) {
        number+=array[i] * Math.pow(10, array.length-1-i);
    }
    return number;
}

Inilah Tes Unit

@Test
public void nextHigherNumberTest() {
    assertThat(ArrayUtils.nextHigherNumber(34722641), is(34724126));
    assertThat(ArrayUtils.nextHigherNumber(123), is(132));
}

0

Saya tahu ini adalah pertanyaan yang sangat lama tetapi saya masih tidak menemukan kode mudah di c #. Ini mungkin membantu orang yang menghadiri wawancara.

class Program
{
    static void Main(string[] args)
    {

        int inputNumber = 629;
        int i, currentIndexOfNewArray = 0;

        int[] arrayOfInput = GetIntArray(inputNumber);
        var numList = arrayOfInput.ToList();

        int[] newArray = new int[arrayOfInput.Length];

        do
        {
            int temp = 0;
            int digitFoundAt = 0;
            for (i = numList.Count; i > 0; i--)
            {
                if (numList[i - 1] > temp)
                {
                    temp = numList[i - 1];
                    digitFoundAt = i - 1;
                }
            }

            newArray[currentIndexOfNewArray] = temp;
            currentIndexOfNewArray++;
            numList.RemoveAt(digitFoundAt);
        } while (arrayOfInput.Length > currentIndexOfNewArray);



        Console.WriteLine(GetWholeNumber(newArray));

        Console.ReadKey();


    }

    public static int[] GetIntArray(int num)
    {
        IList<int> listOfInts = new List<int>();
        while (num > 0)
        {
            listOfInts.Add(num % 10);
            num = num / 10;
        }
        listOfInts.Reverse();
        return listOfInts.ToArray();
    }

    public static double GetWholeNumber(int[] arrayNumber)
    {
        double result = 0;
        double multiplier = 0;
        var length = arrayNumber.Count() - 1;
        for(int i = 0; i < arrayNumber.Count(); i++)
        {
            multiplier = Math.Pow(10.0, Convert.ToDouble(length));
            result += (arrayNumber[i] * multiplier);
            length = length - 1;
        }

        return result;
    }
}

0

Implementasi yang sangat sederhana menggunakan Javascript, angka tertinggi berikutnya dengan digit yang sama

/*
Algorithm applied
I) Traverse the given number from rightmost digit, keep traversing till you find a digit which is smaller than the previously traversed digit. For example, if the input number is “534976”, we stop at 4 because 4 is smaller than next digit 9. If we do not find such a digit, then output is “Not Possible”.

II) Now search the right side of above found digit ‘d’ for the smallest digit greater than ‘d’. For “534976″, the right side of 4 contains “976”. The smallest digit greater than 4 is 6.

III) Swap the above found two digits, we get 536974 in above example.

IV) Now sort all digits from position next to ‘d’ to the end of number. The number that we get after sorting is the output. For above example, we sort digits in bold 536974. We get “536479” which is the next greater number for input 534976.

*/

function findNext(arr)
{
  let i;
  //breaking down a digit into arrays of string and then converting back that array to number array
  let arr1=arr.toString().split('').map(Number) ;
  //started to loop from the end of array 
  for(i=arr1.length;i>0;i--)
  {
    //looking for if the current number is greater than the number next to it
    if(arr1[i]>arr1[i-1])
    {// if yes then we break the loop it so that we can swap and sort
      break;}
  }

  if(i==0)
  {console.log("Not possible");}

   else
  {
   //saving that big number and smaller number to the left of it
   let smlNum =arr1[i-1];
    let bigNum =i;
   /*now looping again and checking if we have any other greater number, if we have one AFTER big number and smaller number to the right. 
     A greater number that is of course greater than that smaller number but smaller than the first number we found.
     Why are doing this? Because that is an algorithm to find next higher number with same digits. 
   */
    for(let j=i+1;j<arr1.length;j++)
      {//What if there are no digits afters those found numbers then of course loop will not be initiated otherwise...
        if(arr1[j]> smlNum && arr1[j]<arr1[i])
        {// we assign that other found number here and replace it with the one we found before
          bigNum=j;

        }
      } //now we are doing swapping of places the small num and big number , 3rd part of alogorithm
    arr1[i-1]=arr1[bigNum];
          arr1[bigNum]=smlNum;
    //returning array 
    //too many functions applied sounds complicated right but no, here is the  trick
    //return arr first then apply each function one by one to see output and then further another func to that output to match your needs
    // so here after swapping , 4th part of alogorithm is to sort the array right after the 1st small num we found
    // to do that first we simple take part of array, we splice it and then we apply sort fucntion, then check output (to check outputs, pls use chrome dev console)
    //and then  simply the rest concat and join to main one digit again.
     return arr1.concat((arr1.splice(i,arr1.length)).sort(function(a, b){return a-b})).join('');



    // Sorry to make it too long but its fun explaining things in much easier ways as much as possible!!
  }

}


findNext(1234);

Karena ada banyak komentar, jadi lebih baik Anda dapat menyalinnya ke editor teks Anda. Terima kasih!


0

Ada banyak jawaban bagus tapi saya tidak menemukan implementasi Java yang layak. Ini dua sen saya:

public void findNext(int[] nums) {
    int i = nums.length - 1;
    // nums[i - 1] will be the first non increasing number
    while (i > 0 && nums[i] <= nums[i - 1]) {
        i--;
    }
    if (i == 0) {
        System.out.println("it has been the greatest already");
    } else {
        // Find the smallest digit in the second sequence that is larger than it:
        int j = nums.length - 1;
        while (j >= 0 && nums[j] < nums[i - 1]) {
            j--;
        }
        swap(nums, i - 1, j);
        Arrays.sort(nums, i, nums.length);
        System.out.println(Arrays.toString(nums));
    }
}

public void swap(int[] nums, int i, int j) {
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

0
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<string.h>
#include<sstream>
#include<iostream>

using namespace std;
int compare (const void * a, const void * b)
{
    return *(char*)a-*(char*)b;
}

/*-----------------------------------------------*/

int main()
{
    char number[200],temp;
    cout<<"please enter your number?"<<endl;
    gets(number);
    int n=strlen(number),length;
    length=n;
    while(--n>0)
    {
        if(number[n-1]<number[n])
        {
            for(int i=length-1;i>=n;i--)
            {
                if(number[i]>number[n-1])
                {
                    temp=number[i];
                    number[i]=number[n-1];
                    number[n-1]=temp;
                    break;
                }
            }
            qsort(number+n,length-n,sizeof(char),compare);
            puts(number); 
            return 0;
        }
    }
    cout<<"sorry itz the greatest one :)"<<endl;
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.