숫자가 주어지면 원래 숫자와 정확히 같은 자릿수가있는 다음 높은 숫자를 찾으십시오.


226

방금 면접을 폭파하고 면접 질문에서 거의 진전이 없었습니다. 누구 든지이 작업을 수행하는 방법을 알려주시겠습니까? 온라인 검색을 시도했지만 아무것도 찾을 수 없습니다.

숫자가 주어지면 원래 숫자와 정확히 같은 자릿수가있는 다음 높은 숫자를 찾으십시오. 예를 들어 : 주어진 38276은 38627을 반환합니다.

첫 번째 숫자 (오른쪽에서)보다 작은 숫자의 인덱스를 찾는 것으로 시작하고 싶었습니다. 그런 다음 하위 집합의 마지막 숫자를 회전하여 같은 숫자로 구성된 다음으로 큰 숫자이지만 멈추었습니다.

면접관은 한 번에 하나씩 숫자를 바꾸라고 제안했지만 알고리즘을 알아낼 수 없었고 20-30 분 정도 화면을 쳐다 보았습니다. 말할 필요도없이, 구직 활동을 계속해야 할 것 같습니다.

편집 : 그 가치에 대해, 나는 다음 번 인터뷰에 초대되었습니다.


15
그것에 대해 너무 많이 생각하지 않고 최소한 시작의 힘은 숫자의 모든 순열을 계산하고 입력 숫자보다 큰 최소 숫자를 가져옵니다.
BrokenGlass

13
C ++에서는 next_permutation;-)를 사용할 수 있습니다 .
dayturns

9
참고로, 여기에 문제를 거의 생각하지 않고 약 15 분 안에 해결하는 방법이 있습니다. 처음 5 자릿수의 알고리즘을 작성하여 일련의 숫자의 가능한 순열을 만들고 정렬하고 표시했습니다. 내가 통해보고 5 분 동안 패턴이 목록에서 등장 할 때까지 데이터 (여기에 솔루션을 수락 한 O (n)은 짧은 시간보고 후 분명 해졌다), 그때는 O (n)의 코딩 알고리즘 5 분을 보냈다.
Ben Lee

1
일반적으로 이것은 붙어있을 때 이런 종류의 문제를 해결하는 알고리즘을 제시하는 나쁜 방법이 아닙니다. 작은 샘플에 무차별 대입을 사용하여 패턴을보다 쉽게 ​​볼 수있는 많은 데이터를 생성하십시오.
Ben Lee

19
나는 또한 당신이 정말로 이것을하는 효율적인 방법을 알 수 없다면, 인터뷰를 실패시키는 확실한 방법은 없다고 지적하고 싶습니다 (비즈니스 세계에서는 제품 마감일을 놓칠 수있는 확실한 방법입니다) . 당신이 포기하는 대신에, 당신은 포기하는 대신, 그것을 무차별하게 강요하고 "TODO : 성능을위한 리팩터링"또는 이와 유사한 것에 댓글을 달아야합니다. 내가 인터뷰 중이고 누군가 그렇게했다면 반드시 실패하지는 않을 것입니다. 적어도 그들은 효과가있는 것을 생각해 내고 그것을 찾을 수 없어도 더 나은 것이 있다는 것을 인식했습니다.
Ben Lee

답변:


272

다음 과 같이 (자릿수는 O(n)어디에 있습니까? n)

오른쪽부터 시작하여 왼쪽 숫자가 오른쪽 숫자보다 작도록 첫 번째 숫자 쌍을 찾습니다. "digit-x"로 왼쪽 숫자를 참조합시다. digit-x의 오른쪽에있는 digit-x보다 작은 숫자를 찾아 digit-x의 바로 왼쪽에 배치하십시오. 마지막으로 남은 자릿수는 오름차순으로 정렬합니다. 이미 내림차순 이므로 숫자를 뒤집기 만하면됩니다 (digit-x의 올바른 위치에 배치 할 수 있음 O(n)) .

예를 들어 이것을 더 명확하게 만들 수 있습니다.

123456784987654321
숫자로 시작하다

123456784 987654321
         ^ 왼쪽 숫자가 오른쪽보다 작은 오른쪽에서 첫 번째 위치  
         숫자 "x"는 4

123456784 987654321
              ^ 오른쪽으로 4보다 큰 가장 작은 숫자를 찾습니다.

123456785 4 98764321
        ^ 4의 왼쪽에 놓으십시오

123456785 4 12346789
123456785123446789
         ^ 5의 오른쪽으로 숫자를 정렬합니다. 
         '4'는 이미 내림차순입니다. 우리가해야 할 일은 
         순서를 바꾸고 '4'에 대한 올바른 장소를 찾으십시오.

정확성 증명 :

대문자를 사용하여 숫자 문자열과 숫자의 소문자를 정의합시다. 구문 AB수단 "문자열 연결 AB" . <lexicographical ordering은 자릿수 문자열의 길이가 동일한 경우 정수 순서와 동일합니다.

우리의 원래 숫자 N의 형식은 AxB, x한 자리이며, B정렬 내림차순입니다.
알고리즘에서 찾은 숫자는 가장 작은 자릿수 (AyC 여기서 선택한 방식 으로 존재해야 함 , 위 참조) 이며 오름차순으로 정렬됩니다.y ∈ B> x xC

같은 숫자를 사용하는 숫자가 있다고 가정 N'합니다 AxB < N' < AyC. N'로 시작 A하거나 그렇지 않으면 그들 사이에 빠질 수 없으므로 양식으로 작성할 수 있습니다 AzD. 이제 우리의 불평등은입니다 AxB < AzD < AyC. xB < zD < yC세 자리 문자열이 모두 같은 자리를 포함하는 것과 같습니다.

그것이 사실이 되려면, 우리는 반드시 있어야합니다 x <= z <= y. 때문에 y작은 숫자입니다 > x, z그래서 하나, 그들 사이가 될 수 없습니다 z = xz = y. 말해봐 z = x. 그리고 우리의 불평등은 xB < xD < yC의미하는 B < D곳 모두 BD같은 자리가 있습니다. 그러나 B는 내림차순으로 정렬되므로 해당 자릿수보다 큰 문자열 없습니다. 따라서 우리는 가질 수 없습니다 B < D. 동일한 단계를 수행하면을 z = y가질 수 없다는 것을 알 수 있습니다 D < C.

따라서 N'존재할 수 없으므로 알고리즘이 다음으로 큰 숫자를 올바르게 찾습니다.


7
좋은 해결책! 질문이 하나 있습니다. "x보다 큰 가장 작은 자릿수"는 y라고 말합니다. x와 y를 바꾸고 x.index + 1-> end를 뒤집을 수 있습니까?
Kent

8
숫자 99999는 어떻게됩니까?
Sterex

19
@Sterex, 그것은 단지 99999가 아닙니다. 숫자가 이미 내림차순으로 완전히 정렬 된 숫자는 최대 값입니다 (따라서 98765에는 해가 없습니다). 알고리즘의 1 단계가 실패하기 때문에 프로그래밍 방식으로 쉽게 검색 할 수 있습니다 ( "왼쪽 숫자가 오른쪽 숫자보다 작음"과 같은 연속 숫자 쌍이 없습니다).
Ben Lee

3
@TMN : 9가 8보다 큽니다. 9를 8의 왼쪽으로 9 832옮긴 다음 9의 오른쪽으로 모든 것을 정렬합니다.9238
BlueRaja-Danny Pflughoeft

4
변경해야 할 일에 대한 당신의 솔루션을 @Kent 4보다 작은 숫자가 큰 찾기 올바른 하는 4보다 작은 숫자가 큰 찾을 수 에서 오른쪽 . 그렇지 않으면 예를 들어 1234567849876 55 4321은 1234567851234 54 6789 (1234567851234 45 6789 대신 )가됩니다. nitpick :-)
osundblad

94

거의 동일한 문제가 코드 걸림 문제로 나타 났으며 여기에 해결책이 있습니다.

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

다음은 예제를 사용하는 방법에 대한 요약입니다.

34722641

A. 일련의 숫자를 두 개로 나누면 오른쪽 부분이 가능한 한 길어지고 순서는 줄어 듭니다.

34722 641

( 전체 숫자가 내림차순이면 숫자를 추가하지 않고는 더 큰 숫자가 없습니다.)

B.1. 첫 번째 시퀀스의 마지막 숫자를 선택하십시오.

3472(2) 641

B.2. 두 번째 시퀀스에서 가장 큰 자릿수보다 큰 숫자를 찾으십시오.

3472(2) 6(4)1

B.3. 스왑 :

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

C. 두 번째 시퀀스를 오름차순으로 정렬하십시오.

34724 126

D. 완료!

34724126

1
오타 : "-> 34721 621"은 "-> 34724 621"이어야한다고 생각하십니까?
bjnord

1
@bjnord 잘 잡았습니다. 결정된. 내가 어떻게 관리했는지 잘 모르겠습니다. 다음 줄에서 정확했습니다.
위블

여기에 +1 최고의 답변입니다. 직관적이고 빠릅니다. (이것은 내가 종이에서 이것을
해결할

1
@Neel-C 단계에서 우리가 정렬하려는 숫자는 B 단계에서 교환 한 숫자를 제외하고 내림차순입니다. 정렬하려면 실제로 숫자를 바꾸고 교환 한 숫자를 올바른 위치로 가져와야합니다. 이것이 BlueRaja가 설명하는 것입니다.
Weeble

1
@Dhavaldave 문제가 무엇입니까? 단계 A에서 "12"와 "3"을 얻습니다. B 단계에서 "13"과 "2"를 얻습니다. C 단계에서 아무것도 변하지 않습니다. 단계 D에서 "132"를 얻습니다. 답을 얻지 못하는 유일한 경우는 "321"과 같이 숫자가 이미 최대 값일 때입니다. 이 경우 단계 A는 ""및 "321"을 제공하며 스플릿의 왼쪽에 빈 시퀀스를 진행할 수 없습니다.
위블

14

다음은 Python의 컴팩트하지만 부분적인 무차별 솔루션입니다.

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

C ++에서는 다음과 같이 순열을 할 수 있습니다 : https : //.com/a/9243091/1149664 (itertools의 알고리즘과 동일한 알고리즘입니다)

다음 은 Weeble 및 BlueRaja (다른 답변)가 설명 하는 최상위 답변구현입니다 . 더 좋은 것이 있는지 의심합니다.

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

누구든지 이것을 업데이트 할 수 있습니까? Python 3에서는과 같이 작동하지 않는 것 같습니다 type 'map' has no len(). 두 번째 줄을로 변경했습니다 iis=list(map(int,str(ii))). 누구든지 if i == 0: return ii선을 설명 할 수 있습니까? 111 또는 531과 같은 입력에서 작동하는 이유는 무엇입니까? 감사.
보웬 리우

ʻlist ()를 iis = ... ´에 추가하여 파이썬 3에서 수정했습니다. 사례 111과 531에는 해결책이 없지만 구현에서 111과 531을 반환합니다. i == 0 줄을 변경하면 더 나은 것을 제외하고 변경할 수 있습니다.
Johan Lundberg

감사. 나는 실제로 다른 방향으로 반복하므로 i == 0에 혼란 스러웠습니다. 내 상황에서는 i == len(iis).
보웬 리우

8

최소한 다음은 무차별 문자열 기반 솔루션의 몇 가지 예입니다. 바로 머리 꼭대기에서 얻을 수 있었을 것입니다.

38276정렬 된 자릿수 목록 은23678

38627정렬 된 자릿수 목록 은23678

무차별 힘 증가, 정렬 및 비교

무차별 대입 솔루션을 따라 문자열로 변환하고 해당 숫자를 사용하여 가능한 모든 숫자를 무차별 대입합니다.

모두 int를 만들고 목록에 넣고 정렬하고 대상 항목 다음에 다음 항목을 가져옵니다.

이것에 30 분을 썼는데 적어도 무차별 대입 방식을 찾지 못했다면, 나는 당신도 고용하지 않을 것입니다.

비즈니스 세계에서 우아하고 느리고 어수선하지만 작업을 수행하는 솔루션은 솔루션이 아예없는 것보다 항상 더 가치가 있습니다. 사실 모든 비즈니스 소프트웨어를 우아하고 느리고 불쾌 하게 설명 합니다 .


1
박쥐에 대한 나의 첫 발언은 "나는 그것을 강제 할 수는 있지만 ..."이었다. 실제로 알고리즘 솔루션이 없다면 실망합니다
bhan

4
면접관이라면 무차별 대입 방식에 만족하지 않을 것입니다.
Ahmad Y. Saleh 2019

@ benjamin han에는 알고리즘 솔루션이 있습니다. 결과를 찾을 때까지 오른쪽에서 시작하여 교체 숫자를 유지하십시오. 이전에 모든 순열을 계산할 필요는 없습니다.
dantuch 2019


@BrokenGlass 확실히 더 나은 솔루션입니다. 방금 그 아이디어를 생각해 낸 다음 알고리즘을 게시했습니다.
onit

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

이 솔루션을 생각해 냈습니다. 질문이 있으시면 문의하십시오.
Ashikodi 2016 년

4

당신의 아이디어

첫 번째 숫자 (오른쪽에서)보다 작은 숫자의 인덱스를 찾는 것으로 시작하고 싶었습니다. 그런 다음 하위 집합의 마지막 숫자를 회전하여 같은 숫자로 구성된 다음으로 큰 숫자이지만 멈추었습니다.

사실 꽤 좋습니다. 마지막 숫자뿐만 아니라 현재 고려되는 것보다 중요도가 낮은 모든 숫자 만 고려해야합니다. 그 전에 도달하기 때문에, 우리는 단조로운 숫자 시퀀스를 가지고 있는데, 그것은 오른쪽 이웃보다 가장 오른쪽에있는 숫자입니다. 관련

1234675
    ^

숫자가 같은 다음 큰 숫자는

1234756

발견 된 숫자는 마지막 숫자 (교환 된 숫자 중 가장 작은 숫자)와 교환되며 나머지 숫자는 증가하는 순서로 정렬됩니다.


4

나는 당신의 면접관이 당신을 다음과 같은쪽으로 부드럽게 밀려 고했다고 확신합니다 :

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

가장 효율적이거나 우아한 솔루션 일 필요는 없지만 제공된 예제를 두 주기로 해결하고 그가 제안한대로 한 번에 하나씩 숫자를 교체합니다.


2

숫자를 가지고 숫자로 나눕니다. 따라서 5 자리 숫자가 있으면 5 자리 숫자가됩니다 : abcde

이제 d와 e를 바꾸고 원래 숫자와 비교하면 더 큰 경우 답을 얻습니다.

더 크지 않으면 e와 c를 바꾸십시오. 이제 스왑 d와 e가 더 작은 경우 (비교 재귀) 비교하고 최소화하십시오.

더 큰 숫자를 찾을 때까지 계속하십시오. 재귀를 사용하면 약 9 줄의 스키마 또는 20 개의 c #으로 작동해야합니다.


2

그것은 매우 흥미로운 질문입니다.

여기 내 자바 버전이 있습니다. 다른 기여자의 의견을 확인하기 전에 패턴을 파악하여 코드를 완전히 완성하는 데 약 3 시간이 걸립니다. 내 생각이 다른 사람들과 상당히 동일하다는 것을 알게되어 기쁘다.

O (n) 용액. 솔직히 시간이 15 분이고 화이트 보드에서 완전한 코드 완성이 필요한 경우이 인터뷰에 실패합니다.

내 솔루션에 흥미로운 점이 있습니다.

  • 정렬을 피하십시오.
  • 스트링 작동을 완전히 피하십시오
  • O (logN) 공간 복잡성 달성

코드에 자세한 설명을 넣고 각 단계마다 Big O를 사용했습니다.

  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;

}

Intellj에서 실행되는 결과는 다음과 같습니다.

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

123의 경우 대답은 무엇입니까? 실제로는 코드가 출력되는 동안 출력을 생성하지 않습니다. 132
Dhaval dave

2

@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

해결책 (자바에서)은 다음과 같습니다 (여기서 친구가 더 잘 찾을 수 있다고 확신합니다) :
숫자가 높아질 때까지 문자열 끝에서 숫자를 바꾸십시오.
즉, 먼저 아래 자릿수를 높이기 시작한 후 다음 높은 숫자를 칠 때까지 다음 높은 숫자를 올리십시오.
그런 다음 나머지를 정렬하십시오. 귀하의 예에서 다음을 얻을 수 있습니다.

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 : Output is .Why 63872, 왜 그래야합니까?
Cratylus 2019

음 .. 다음 높은 숫자? :) 그것이 요구 사항 이었습니까?
Karoly Horvath 2012

@BlueRaja - 대니 Pflughoeft은 다음과 같이 도와 준거 주셔서 감사합니다 코드를 변경 : (지금까지 높은 숫자를 산출하는) 가장 자리 선불 이동 및 정렬 나머지
Cratylus

1

C ++로 프로그래밍하는 경우 다음을 사용할 수 있습니다 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;
}

입력하면 어떻게 100되나요? :-)
jweyrich

1

이 질문에 답할 때 무차별 대입 알고리즘에 대해 아무것도 몰랐으므로 다른 각도에서 접근했습니다. number_given + 1부터 사용 가능한 최대 수 (3 자리 숫자의 경우 999, 4 자리 숫자의 경우 9999 등)까지이 숫자를 다시 정렬 할 수있는 가능한 모든 솔루션을 검색하기로 결정했습니다. 각 솔루션의 숫자를 정렬하고 매개 변수로 주어진 정렬 된 숫자와 비교하여 단어가있는 회문을 찾는 것과 같은 종류의 작업을 수행했습니다. 그런 다음 솔루션 배열에서 첫 번째 솔루션을 반환했습니다. 이것이 가능한 다음 값이 될 것입니다.

다음은 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

이 솔루션의 시간 복잡성은 무엇입니까?
Nitish Upreti

@ Myth17 테스트 한 적이 없으므로 확실하지 않습니다. 그래도 알아 내려면이 게시물을 확인하십시오 : stackoverflow.com/questions/9958299/…
Jeremiah McCurdy

1

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

나는 이것을 두 개의 숫자로만 테스트했습니다. 그들은 일 했어. 지난 12 월 은퇴 할 때까지 8 년 동안 IT 관리자로서 나는 다음 세 가지를 염두에 두었습니다. 1) 정확성 : 작동하면 항상 좋습니다. 2) 속도 : 사용자가 수용 할 수 있어야합니다. 3) 명확성 : 아마 당신만큼 똑똑하지는 않지만, 나는 당신을 지불하고 있습니다. 하고있는 일을 영어로 설명하십시오.

오마르, 행운을 빕니다.

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

여기 내 코드가 있습니다. 이 예제 의 수정 된 버전입니다.

도서관:

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

테스트:

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

    int b = NumPermExample.nextPermutation(a);

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

0

주어진 n 자리 숫자에 9를 더하십시오. 그런 다음 한도 (첫 번째 (n + 1) 자릿수) 내에 있는지 확인하십시오. 그렇다면 새 숫자의 숫자가 원래 숫자의 숫자와 같은지 확인하십시오. 두 조건이 모두 참일 때까지 9를 더 추가하십시오. 숫자가 한계를 초과하면 algo를 중지하십시오.

이 방법에 대해 모순되는 테스트 사례를 만들 수 없었습니다.


1
작동하지만 매우 느립니다. 선형 시간으로 해결할 수있는 지수 시간 알고리즘입니다.
interjay

0

파이썬을 사용하는 또 다른 솔루션 :

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)

산출:

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

아래는 숫자의 모든 순열을 생성하는 코드입니다. String.valueOf (integer)를 사용하여 해당 정수를 문자열로 변환해야합니다.

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

또 다른 Java 구현은 즉시 실행 가능하며 테스트로 완료되었습니다. 이 솔루션은 좋은 오래된 동적 프로그래밍을 사용하여 O (n) 공간과 시간입니다.

무차별 대입을 원한다면 두 종류의 무차별 대입이 있습니다.

  1. 모든 것을 퍼 미트 한 다음 분을 더 높게 선택하십시오 : O (n!)

  2. 이 구현과 유사하지만 DP 대신 indexToIndexOfNextSmallerLeft 맵을 채우는 단계를 무차별 적으로 수행하면 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

가장 오른쪽에있는 비트 0과 1을 찾아서 가장 오른쪽에있는 0 비트를 1로 뒤집어 야합니다.

예를 들어 입력이 487, 이진수로 111100111이라고 가정 해 봅시다.

우리는 그 다음에 1이있는 가장 오른쪽으로 0을 뒤집습니다.

그래서 우리는 111101111을 얻습니다

그러나 이제 우리는 여분의 1과 하나의 0을 갖지 않으므로 플립 비트의 오른쪽에있는 1의 수를 1 씩 줄이고 0의 수를 1 씩 증가 시켜서

111101011-이진 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

다음은 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;
}

다음은 단위 테스트입니다

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

0

나는 이것이 매우 오래된 질문이라는 것을 알고 있지만 여전히 C #에서 쉬운 코드를 찾지 못했습니다. 이것은 인터뷰에 참석하는 사람들에게 도움이 될 수 있습니다.

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를 사용한 매우 간단한 구현

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

주석이 많으므로 텍스트 편집기로 복사하는 것이 좋습니다. 감사!


0

좋은 답변이 많이 있지만 괜찮은 Java 구현을 찾지 못했습니다. 여기 내 두 센트가 있습니다 :

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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.