Bir sayı verildiğinde, orijinal sayıyla tam olarak aynı basamak kümesine sahip bir sonraki yüksek sayıyı bulun


226

Bir röportajı bombaladım ve röportaj sorumda neredeyse sıfır ilerleme kaydettim. Bunu nasıl yapacağımı bana kimse bilebilir mi? Çevrimiçi arama yapmayı denedim ama hiçbir şey bulamadım:

Bir sayı verildiğinde, orijinal sayıyla aynı basamak kümesine sahip olan bir sonraki yüksek sayıyı bulun. Örneğin: verilen 38276 dönüşü 38627

İlk basamağın (sağdan) daha az olanın dizinini bularak başlamak istedim. Sonra altkümedeki son basamakları, aynı basamaklardan oluşan bir sonraki en büyük sayı olacak şekilde döndürürdüm, ancak sıkıştı.

Görüşmeci aynı zamanda rakamları birer birer değiştirmeye çalışmayı önerdi, ancak algoritmayı anlayamadım ve sadece 20-30 dakika boyunca bir ekrana baktım. Söylemeye gerek yok, sanırım iş aramaya devam edeceğim.

edit: onun değeri ne için, ben röportaj sonraki tur davet edildi


15
çok fazla düşünmeden en azından bir başlangıç, kaba kuvvet, rakamların tüm permütasyonlarını hesaplar ve giriş numarasından daha büyük olan minimum sayıyı
yakalar

13
C ++ 'da sadece kullanabilirsiniz next_permutation;-)
thedayturns

9
FYI, sorunu yaklaşık olarak düşünürken bile yaklaşık 15 dakikada çözdüm: İlk önce 5 dakika geçirdim, sadece bir dizi rakamın tüm olası permütasyonlarını yaratan, sıralayan ve görüntüleyen bir kaba kuvvet algoritması yazdım. Listeden bir örüntü çıkana kadar bu verileri inceleyerek 5 dakika geçirdim (burada O (n) kabul edilen çözüm kısa bir süre sonra netleşti), sonra O (n) algoritmasını kodlamak için 5 dakika geçirdim.
Ben Lee

1
Genel olarak, bu takıldığınızda bu tür bir sorunu çözmek için algoritmalar bulmak için kötü bir yol değildir - daha sonra desenleri daha kolay görmek için kullanabileceğiniz çok sayıda veri oluşturmak için bazı ufacık örneklerde kaba kuvvet kullanın.
Ben Lee

19
Ayrıca şunu da belirtmek isterim ki, bunu yapmak için gerçekten etkili bir yol bulamıyorsanız, hiçbir şey yapmamak röportajı geçmenin kesin bir yoludur (ve iş dünyasında, bir ürün son tarihini kaçırmanın kesin bir yoludur) . Takıldığınızda, vazgeçmek yerine, sadece kaba zorlamalısınız ve "TODO: performans için refactor" ya da bunun gibi bir şeye yorum yapmalısınız. Eğer röportaj yapsaydım ve birisi bunu yapsaydı, onları mutlaka başarısız olmazdım. En azından işe yarayan bir şey buldular ve bulamasalar bile daha iyi bir şey olduğunu fark ettiler.
Ben Lee

Yanıtlar:


272

Bunu (basamak sayısı O(n)nerede n) şu şekilde yapabilirsiniz:

Sağdan başlayarak, ilk basamak çiftini, sol basamak sağ basamaktan daha küçük olacak şekilde bulursunuz. Sol basamağa "basamak-x" ile bakalım. X basamağının sağındaki x basamağından daha büyük olan en küçük sayıyı bulun ve x basamağının hemen soluna yerleştirin. Son olarak, kalan basamakları artan sırada sıralayın - zaten azalan sırada olduklarından , yapmanız gereken tek şey onları tersine çevirmek (doğru yere yerleştirilebilen basamak x için kaydedin O(n)) .

Bir örnek bunu daha açık hale getirecektir:

123456784987654321
bir numara ile başla

123456784 987654321
         ^ sol basamağın sağdan daha az olduğu sağdan ilk yer  
         Basamak "x" 4'tür

123456784 987654321
              ^ Sağda 4'ten büyük en küçük rakamı bulun

123456785 4 98764321
        ^ 4'ün soluna yerleştirin

123456785 4 12346789
123456785123446789
         ^ 5'in sağındaki rakamları sıralayın. 
         '4' zaten azalan sıradaydı, tek yapmamız gereken 
         siparişlerini tersine çevirin ve '4' için doğru yeri bulun

Doğruluk kanıtı:

Rakam dizelerini ve rakamlar için küçük harfleri tanımlamak için büyük harfler kullanalım. Sözdizimi ABaracı "dizeleri birleştirme Ave B" . <sözcük dizisi, basamak dizeleri eşit uzunlukta olduğunda tamsayı sıralaması ile aynıdır.

Orijinal N numaramız AxB, xtek basamaklı ve Bazalan şekilde sıralanan formdadır .
Numara olan bizim algoritması tarafından bulundu AyCnerede, y ∈ Bküçük sayıdır > x (bu yol nedeniyle bulunması gerekir xseçildi yukarıya bakınız) ve Csıralı artan olduğunu.

Varsayalım ki (aynı rakamları kullanarak) bir sayı N'vardır AxB < N' < AyC. N'ile başlamalı Aya da aralarında düşemezdi, böylece formda yazabiliriz AzD. Şimdi eşitsizliğimiz, her üç rakam dizesinin de aynı rakamları içerdiği yerle AxB < AzD < AyCeşdeğerdir xB < zD < yC.

Bunun gerçek olabilmesi için sahip olmalıyız x <= z <= y. Yana yen küçük rakamdır > x, zbu yüzden ya, aralarında olamaz z = xya z = y. Söyle z = x. Sonra bizim eşitsizlik olduğu xB < xD < yCanlamına gelir B < Dnereye hem Bve Daynı basamaktan. Ancak, B sıralı inen bu yüzden orada olması ise bunun daha büyük olanlar basamağı ile hiçbir dize. Böylece sahip olamayız B < D. Aynı adımları takiben, eğer görüyoruz z = y, biz olamaz D < C.

Bu nedenle var N'olamaz, yani algoritmamız bir sonraki en büyük sayıyı doğru bir şekilde bulur.


7
güzel bir çözüm! bir sorum var. "x'den büyük en küçük basamak" y diyelim. sadece x ve y'yi değiştirebilir miyiz, sonra x.index + 1 -> sonunu tersine çevirebilir miyiz?
Kent

8
99999 numarasına ne olur?
Sterex

19
@Sterex, sadece 99999 değil; basamakları azalan sırada zaten tam olarak sıralanan herhangi bir sayı maksimumdur (yani 98765'in de çözümü yoktur). Bu, programlı olarak tespit edilmesi kolaydır, çünkü algoritmanın 1. adımı başarısız olur ("sol basamak sağ basamaktan daha küçük" olacak şekilde ardışık basamak çifti yoktur).
Ben Lee

3
@TMN: 9 8'den büyüktür, bu nedenle 9'u 8'in soluna taşırsınız: daha 9 832sonra her şeyi 9'un 9238
sağına sıralarsınız

4
Değiştirmek zorunda kalacak işinize çözümü için @Kent 4'ten küçük basamaklı büyük bulmak için sağa için 4'ten küçük basamaklı büyük bulmak dan sağa . Aksi takdirde, örneğin 1234567849876 55 4321, 1234567851234 54 6789 ile sonuçlanacaktır (1234567851234 45 6789 yerine ). A nitpick :-)
osundblad

94

Neredeyse özdeş bir sorun Code Jam sorunu olarak ortaya çıktı ve burada bir çözümü var:

http://code.google.com/codejam/contest/dashboard?c=186264#s=a&a=1

İşte bir örnek kullanarak yöntemin bir özeti:

34722641

A. Rakam sırasını ikiye bölün, böylece sağ kısım azalan sırada kalırken mümkün olduğu kadar uzun olacaktır:

34722 641

( Sayının tamamı azalan sıradaysa, rakam eklemeden yapılacak daha büyük bir sayı yoktur.)

B.1. İlk dizinin son basamağını seçin:

3472(2) 641

B.2. İkinci sırada, ondan daha büyük olan en küçük rakamı bulun:

3472(2) 6(4)1

B.3. Onları değiştirin:

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

C. İkinci sırayı artan düzene göre sıralayın:

34724 126

D. Yapıldı!

34724126

1
Yazım hatası: Bence "-> 34721 621" "-> 34724 621" olmalı?
bjnord

1
@bjnord İyi yakaladın. Sabit. Bunu nasıl başardığımdan emin değilim - sonraki satırlarda doğruydu.
Weeble

+1 En iyi cevap burada. Sezgisel ve hızlı. (bunu kağıt üzerinde çalıştığımda da düşündüm;))
Muhd

1
@Neel - C adımında, sıralamak istediğimiz rakamlar, B adımında takas ettiğimiz rakam hariç, azalan sıradadır. Bunları sıralamak için, aslında sadece onları tersine çevirmeli ve takas edilen rakamı doğru konuma getirmeliyiz. BlueRaja bunu açıklıyor.
Weeble

1
@Dhavaldave Sorun nedir? A adımında "12" ve "3" elde edersiniz. B adımında "13" ve "2" elde edersiniz. C adımında hiçbir şey değişmez. D adımında "132" elde edersiniz. Cevap alamayacağınız tek durum, numaranın mümkün olan maksimum sayı olduğu zamandır, örneğin "321". Bu durumda, adım A size "" ve "321" verir ve bölmenin sol tarafı için boş bir sekansla devam edemezsiniz.
2013 Weeble

14

İşte Python'da kompakt (ama kısmen kaba kuvvet) bir çözüm

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

C ++ 'da permütasyonları şu şekilde yapabilirsiniz: https://stackoverflow.com/a/9243091/1149664 (itertools'daki ile aynı algoritmadır)

Weeble ve BlueRaja tarafından açıklanan en iyi cevabın bir uygulaması (diğer cevaplar). Daha iyi bir şey olduğundan şüpheliyim.

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)))))

Herkesin bunu güncelleme şansı var mı? Gösterildiği gibi Python 3'te çalışmıyor gibi görünüyor type 'map' has no len(). Ben sadece 2. satırı olarak değiştirirdim iis=list(map(int,str(ii))). Ve kimse if i == 0: return iihattı açıklayabilir mi? Neden 111 veya 531 gibi girdilerle çalışır? Teşekkürler.
Bowen Liu

İis = ... ´ öğesine ´list () ekleyerek şimdi python 3 için düzelttim. 111 ve 531 numaralı davaların çözümü yoktur ancak benim uygulamam bunlar için 111 ve 531 olarak geri dönmektedir. Bunu, i == 0 satırını değiştirerek bulduğunuz şeyin daha iyi bir istisna olarak değiştirebilirsiniz.
Johan Lundberg

Teşekkürler. Aslında benim durumumda olurken ben i == 0 ile karıştırıldı bu yüzden diğer yönde döngü i == len(iis).
Bowen Liu

8

En azından, kafanızın üstünden gelebilmeniz gereken birkaç örnek kaba kuvvet String tabanlı çözüm var:

38276sıralı rakamların listesi23678

38627sıralı rakamların listesi23678

kaba kuvvet artışı, sıralama ve karşılaştırma

Kaba kuvvet çözümleri boyunca bir Dize ve kaba kuvvet bu rakamları kullanarak tüm olası sayıları dönüştürmek olacaktır.

Bunların hepsinden ints oluşturun, bir listeye koyun ve sıralayın, hedef girişten sonraki sonraki girişi alın.

Bu konuda 30 dakika geçirdiyseniz ve en azından kaba kuvvet yaklaşımı bulamadıysanız, ben de sizi işe almazdım.

İş dünyasında, beceriksiz, yavaş ve hantal ama işi yapan bir çözüm, hiç bir çözümden daha değerli, aslında tüm iş yazılımlarını, yetersiz, yavaş ve hantal olarak tanımlamaktadır .


1
Peki yarasadan ilk yorumum "Kaba kuvvet uygulayabilirdim ama ..." idi. Gerçekten algoritmik bir çözüm yoksa, biraz hayal kırıklığına uğradım
bhan

4
Görüşmeci olsaydım, kaba kuvvet yaklaşımından pek memnun olmazdım.
Ahmad Y. Saleh

@benjamin han, algoritmik bir çözüm var. Sonucu bulana kadar rakamları sağdan başlayarak değiştirmeye devam edin. Daha önce tüm permutatnios'u hesaplamaya gerek yoktur.
dantuch

7
Kesinlikle kaba kuvvetten çok daha iyi çözümler var, örneğin ardendertat.com/2012/01/02/…
BrokenGlass

@BrokenGlass Kesinlikle çok daha iyi bir çözüm. Ben sadece bu fikri buluyordum ve sonra algoritmayı yayınladın.
onit

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

Bu çözümü buldum. Lütfen herhangi bir sorunuz varsa sorun.
Ashikodi

4

Senin fikrin

İlk basamağın (sağdan) daha az olanın dizinini bularak başlamak istedim. Sonra altkümedeki son basamakları, aynı basamaklardan oluşan bir sonraki en büyük sayı olacak şekilde döndürürdüm, ancak sıkıştı.

aslında oldukça iyi. Sadece son basamağı değil, şu anda düşünülenden daha az önemli olan tüm basamakları dikkate almanız gerekir. Buna ulaşılmadan önce, monotonik bir basamak dizisine sahibiz, yani sağ komşusundan daha küçük rakam. Saygı

1234675
    ^

Aynı basamaklara sahip bir sonraki büyük sayı

1234756

Bulunan basamak son basamak için değiştirilir - dikkate alınan basamakların en küçüğü - ve kalan basamaklar artan sırada düzenlenir.


4

Görüşmecinizin sizi nazikçe böyle bir şeye doğru itmeye çalıştığından eminim:

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);

Mutlaka en verimli veya zarif çözüm değil, sağlanan örneği iki döngüde çözer ve rakamları önerdiği gibi birer birer değiştirir.


2

Bir sayı alın ve rakamlara bölün. 5 basamaklı bir sayımız varsa, 5 basamakımız var: abcde

Şimdi d ve e'yi değiştirin ve orijinal numarayla karşılaştırın, eğer daha büyükse, cevabınız var.

Daha büyük değilse, e ve c'yi değiştirin. Şimdi karşılaştırın ve daha küçük takas d ve e ise (özyineleme dikkat edin), en küçük alın.

Daha büyük bir sayı bulana kadar devam edin. Özyineleme ile yaklaşık 9 satır veya c # 20 satır olarak çalışmalıdır.


2

Bu çok ilginç bir soru.

İşte benim java versiyonum. Diğer katılımcıların yorumlarını kontrol etmeden önce kodu tamamen bitirmek için kalıbı bulmamdan yaklaşık 3 saat ayırın. Fikrimin başkalarıyla aynı olduğunu görmekten memnunum.

O (n) çözeltisi. Dürüst olmak gerekirse, zaman sadece 15 dakika ise ve beyaz tahtada tam kod bitimi gerektiriyorsa, bu röportajda başarısız olacağım.

İşte benim çözümüm için bazı ilginç noktalar:

  • Herhangi bir sıralama kaçının.
  • Dize işleminden tamamen kaçının
  • O (logN) uzay karmaşıklığına ulaşın

Koduma ve Big O'ya her adımda ayrıntılı yorum koydum.

  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;

}

İşte Intellj'de çalışan sonuç:

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

123 durumunda cevap ne olacak? Pratik olarak u kodu 132
Dhaval dave

2

@ BlueRaja algoritmasının javascript uygulaması.

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

Bir çözüm (Java'da) aşağıdaki olabilir (Eminim burada arkadaşlar daha iyi bulabilirler): Daha
yüksek bir sayı elde edene kadar dizenin sonundaki rakamları değiştirmeye başlayın.
İlk önce alt basamağı yukarı hareket ettirmeye başlayın, sonra bir sonraki yüksek vb.
Sonra geri kalanını sıralayın. Örneğinizde şunları elde edersiniz:

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: Çıktı 63872.Neden, ne olmalı?
Cratylus

peki .. sonraki yüksek sayı? :) bu şarttı, değil mi?
Karoly Horvath

@BlueRaja - Danny Pflughoeft: Yardımınız için teşekkürler.Kodu aşağıdaki gibi değiştirdim: En küçük rakamı öne doğru hareket ettirin (ki bu daha yüksek bir sayı verir) ve gerisini sıralayın
Cratylus

1

C ++ 'da programlama yapıyorsanız, aşağıdakileri kullanabilirsiniz 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;
}

Girersem ne olur 100? :-)
jweyrich

1

Bu soruyu cevaplarken kaba kuvvet algoritması hakkında hiçbir şey bilmiyordum, bu yüzden başka bir açıdan yaklaştım. Number_given + 1'den mevcut maksimum sayıya kadar (3 basamaklı bir sayı için 999, 4 basamaklı 9999 vb.) Başlayarak, bu sayının yeniden düzenlenebileceği tüm olası çözümleri aramaya karar verdim. Bu tür bir kelimeyi, her çözümün sayılarını sıralayarak ve parametre olarak verilen sıralı sayı ile karşılaştırarak bir palindrom bulmak gibi yaptım. Daha sonra basitçe, bir sonraki olası değer olacağı için çözüm dizisindeki ilk çözümü döndürdüm.

İşte benim kod 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

bu çözümün zaman karmaşıklığı nedir?
Nitish Upreti

@ Myth17 Hiç test etmediğimden emin değilim. Gerçi anlamak istiyorsanız, bu
Jeremiah McCurdy

1

PHP Kodu

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

Bunu sadece iki rakamla test ettim. Onlar çalıştı. BT Yöneticisi olarak geçen Aralık ayında emekli oluncaya kadar 8 yıl boyunca üç şeye önem verdim: 1) Doğruluk: Çalışıyorsa iyi - her zaman. 2) Hız: kullanıcı tarafından kabul edilebilir olmalıdır. 3) Netlik: Muhtemelen senin kadar zeki değilim, ama sana para ödüyorum. Ne yaptığınızı İngilizce olarak açıkladığınızdan emin olun.

Ömer, iyi şanslar ilerliyor.

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

İşte kodum, değiştirilmiş bir sürümü bu örneğin

Kütüphane:

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;
    }
}

Ölçek:

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

    int b = NumPermExample.nextPermutation(a);

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

0

Verilen n basamaklı sayıya 9 ekleyin. Ardından sınırın dahilinde olup olmadığını kontrol edin (ilk (n + 1) basamak sayısı). Eğer öyleyse, yeni sayıdaki rakamların orijinal sayıdaki rakamlarla aynı olup olmadığını kontrol edin. Her iki koşul da doğru olana kadar 9 eklemeyi tekrarlayın. Sayı sınırı aştığında algoyu durdurun.

Bu yöntem için çelişkili bir test durumu bulamadım.


1
Çalışıyor, ancak son derece yavaş. Bu, lineer zamanda çözülebilecek üstel bir zaman algoritmasıdır.
interjay

0

Python kullanan başka bir çözüm:

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)

Çıktı:

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

Aşağıda, bir sayının tüm permütasyonlarını oluşturmak için kod vardır. Ancak, önce String.valueOf (integer) kullanarak bu tamsayıyı dizeye dönüştürmek gerekir.

/**
 * 
 * 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

Yine başka bir Java uygulaması, kutudan çıkartılabilir ve testlerle tamamlanmıştır. Bu çözüm iyi eski dinamik programlama kullanılarak O (n) uzay ve zamandır.

Biri kaba kuvvet istiyorsa, 2 çeşit kaba kuvvet vardır:

  1. Her şeye izin ver, sonra min daha yüksek seç: O (n!)

  2. Bu uygulamaya benzer, ancak DP yerine, indexToIndexOfNextSmallerLeft haritasını doldurma adımını bruteforcing O (n ^ 2) içinde çalışacaktır.


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

En doğru bit 0'ı ve ardından 1'i bulmamız ve en sağda 0 biti 1'e çevirmemiz gerekir.

örneğin, girdimizin 487 olduğunu söyleyebiliriz, ki bu 111100111 ikiliktir.

1'i takip eden en sağdaki 0'ı çeviririz

yani 111101111 alıyoruz

ama şimdi fazladan 1 ve bir tane daha az 0 var, bu yüzden flip bitinin sağındaki 1'lerin sayısını 1 azaltıyoruz ve 0 bitin sayısını 1 arttırıyoruz.

111101011 - ikili 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

İşte Java Uygulaması

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;
}

İşte Birim Testleri

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

0

Bu çok eski bir soru olduğunu biliyorum ama yine de kolay kod c # bulamadık. Bu, röportajlara katılan erkeklere yardımcı olabilir.

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

Javascript kullanarak aynı basamağa sahip bir sonraki en yüksek sayı

/*
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);

Çok sayıda yorum olduğundan, metin düzenleyicinize kopyalayabilirsiniz. Teşekkürler!


0

Çok iyi cevaplar var ama iyi bir Java uygulaması bulamadım. İşte iki sentim:

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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.