정수 N이 주어집니다. 숫자보다 0 또는 1 만있는 N보다 큰 가장 작은 정수는 무엇입니까?


15

정수 N이 있습니다. 0 또는 1 이외의 숫자를 포함하지 않는 N보다 큰 가장 작은 정수를 찾아야합니다. 예를 들면 N = 12다음과 같습니다 100. C ++에서 무차별 대입 방식을 코딩했습니다.

int main() {
    long long n;
    cin >> n;

    for (long long i = n + 1; ; i++) {
        long long temp = i;
        bool ok = true;
        while (temp != 0) {
            if ( (temp % 10) != 0 && (temp % 10) != 1) {
                ok = false;
                break;
            }
            temp /= 10;
        }
        if (ok == true) {
            cout << i << endl;
            break;
        }
    }
}

문제는 내 접근 방식이 너무 느리다는 것입니다. 나는 이것을 해결하기 위해 매우 효율적인 접근법이 있다고 생각합니다. 이 문제를 효율적으로 해결하려면 어떻게해야합니까?


4
단위부터 시작하십시오. 숫자가 0 또는 1이 아닌 경우 0을 입력하고 1을 갖습니다. 각 위치에 대해 반복
Sembei Norimaki

1
이것은 비슷한 문제를 설명합니다. 어쩌면 도움
TomBombadil

부정적으로 N허용됩니까? 또한 유형이 넘칠 위험이 있으므로 어렵습니다. 한계는 무엇입니까 N?
Bathsheba

1
@ SembeiNorimaki : 이것은 잘못되었습니다. 0과 1로만 이루어진 숫자는 변경되지 않고 그대로 남게됩니다. 그리고 다른 오류도 있습니다.
이브 다우 스트

1
@ SembeiNorimaki : 다른 실패가 있다고 말했습니다. 그들은 당신의 방법이 잘못되어 남아 있습니다. 1에서 50까지의 정수를 시도하면 실수를 찾을 수 있습니다. 인간형을 지우고, diabolicum을 유지하십시오.
이브 다우 스트

답변:


20
  1. 증가 N,

  2. 왼쪽에서 시작하여 1보다 큰 숫자를 찾을 때까지 스캔하십시오. 1보다 큰 부분 수를 늘리고 나머지는 0으로 만드십시오.

예 :

12 -> 13 -> 1|3 -> 10|0
101 -> 102 -> 10|2 -> 11|0
109 -> 110 -> 110|
111 -> 112 -> 11|2 -> 100|0
198 -> 199 -> 1|99 -> 10|00
1098 -> 1099 -> 10|99 -> 11|00
10203 -> 10204 -> 10|204 -> 11|000
111234 -> 111235 -> 111|235 -> 1000|000
...

증명:

요청 된 숫자는 N + 1 이상이어야합니다. 이것이 증가하는 이유입니다. 우리는 이제 더 크거나 같은 숫자를 찾고 있습니다.

우리가 부르 자 접두사에게 초기 0/1 숫자와 접미사 뒤에 오는 무엇을. 접미사의 첫 번째 숫자를 0으로 바꾸고 더 큰 접두사를 설정해야합니다. 가장 작은 접두사는 현재 접두사에 1을 더한 것입니다. 그리고 가장 작은 접미사는 모두 0입니다.


최신 정보:

접두어를 2 진수 로 증가시켜야한다는 것을 잊었습니다 . 그렇지 않으면 금지 된 숫자가 나타날 수 있습니다.


7

다른 가능성은 다음과 같습니다.

  • 사용 된 데이터 유형이 지원하는 "1111111 ... 1111"유형의 최대 10 진수로 시작합니다.

    알고리즘은 입력이이 숫자보다 작다고 가정합니다. 그렇지 않으면 다른 데이터 형식을 사용해야합니다.

    예 :를 사용할 때 long long숫자로 시작합니다 1111111111111111111.

  • 그런 다음 왼쪽에서 오른쪽으로 각 10 진수를 처리하십시오.
    • 숫자를 1에서 0으로 변경하십시오.
    • 결과가 여전히 입력보다 큰 경우 변경을 수행하십시오 (숫자를 0으로 변경).
    • 그렇지 않으면 숫자는 1로 유지됩니다.

Input = 10103
Start:  111111
Step 1: [1]11111, try [0]11111; 011111 > 10103 => 011111 
Step 2: 0[1]1111, try 0[0]1111; 001111 < 10103 => 011111
Step 3: 01[1]111, try 01[0]111; 010111 > 10103 => 010111
Step 4: 010[1]11, try 010[0]11; 010011 < 10103 => 010111
Step 5: 0101[1]1, try 0101[0]1; 010101 < 10103 => 010111
Step 6: 01011[1], try 01011[0]; 010110 > 10103 => 010110
Result: 010110

정확성 증명 :

이 알고리즘에서는 숫자를 숫자로 처리합니다. 각 단계에는 값을 이미 알고있는 숫자와 값을 아직 모르는 숫자가 있습니다.

각 단계에서 가장 왼쪽에있는 숫자를 조사합니다.

이 숫자를 "0"으로 설정하고 다른 모든 알 수없는 숫자를 "1"로 설정했습니다. 프로브 할 숫자가 알 수없는 숫자 중에서 가장 중요하므로 결과 숫자는 해당 숫자가 "0"인 가능한 최대 숫자입니다. 이 숫자가 입력 값보다 작거나 같으면 탐색중인 숫자는 "1"이어야합니다.

반면, 결과 숫자는 프로브중인 숫자가 "1"인 모든 가능한 숫자보다 작습니다. 결과 숫자가 입력보다 큰 경우 숫자는 "0"이어야합니다.

즉, 각 단계에서 한 자리를 계산할 수 있습니다.

C 코드

(C 코드도 C ++에서 작동해야합니다) :

long long input;
long long result;
long long digit;

... read in input ...

result = 1111111111111111111ll;
digit = 1000000000000000000ll;

while( digit > 0 )
{
    if(result - digit > input)
    {
        result -= digit;
    }
    digit /= 10;
}

... print out output ...

3

몇 가지 대안을 제안하겠습니다.

I. 증분. @YvesDaoust 메소드의 수정을 고려하십시오.

  1. N을 1 증가
  2. 선행 0으로 결과 확장
  3. 마지막 숫자에서 두 번째 숫자로 이동
    (a) 2보다 작 으면 모든 것을 그대로 둡니다.
    (b) 그렇지 않으면 0으로 설정하고 를 늘리십시오
  4. 3a, b 단계를 반복하십시오.

예 :

1. N = 0 -> 1 -> (0)|(1) -> 1
2. N = 1 -> 2 -> (0)|(2) -> (1)|(0) -> 10
3. N = 101 -> 102 -> (0)|(1)(0)(2) -> (0)|(1)(1)(0) -> (0)|(1)(1)(0) -> (0)|(1)(1)(0) -> 110
4. N = 298 -> 299 -> (0)|(2)(9)(9) -> (0)|(2)(10)(0) -> (0)|(3)(0)(0) -> (1)|(0)(0)(0) -> 1000

10 진수 형식으로 결과를 얻습니다.


II. 나누기.

  1. N을 1 증가
  2. 합계를 0으로 설정
  3. 결과를 10으로 나누면 div (D) 및 mod (M) 부분이 표시됩니다.
  4. M 확인
    (a) M이 1을 초과하면 D 증가
    (b)를 다르게 M * (10)에 의해 합이 증가 케이 (0부터), k는 현재의 반복 수이고,
  5. D가 0이 될 때까지 3,4 단계를 반복하십시오.

예 1 :

1. N = 0 -> N = 1
2. sum = 0
3. 1/10 -> D == 0, M == 1 -> sum = sum + 1*10^0 == 1
4. D == 0 -> sum == 1

예 2 :

1. N = 1 -> N = 2
2. sum = 0
3. 2/10 -> D == 0, M == 2 -> D = D + 1 == 1
4. 1/10 -> D == 0, M == 1 -> sum = sum + 1*10^1 == 10
5. D == 0, sum == 10

예 3 :

1. N = 101 -> N = 102
2. sum = 0
3. 102/10 -> D == 10, M == 2 -> D = D + 1 == 11
4. 11/10 -> D == 1, M == 1 -> sum = sum + 1*10^1 = 10
5. 1/10 -> D == 0, M == 1 -> sum = sum + 1*10^2 == 10 + 100 == 110
6. D == 0, sum == 110

예 4 :

1. N = 298 -> N = 299
2. sum = 0
3. 299/10 -> D == 29, M == 9 -> D = D + 1 == 30
4. 30/10 -> D == 3, M == 0 -> sum = sum + 0*10^1 == 0
5. 3/10 -> D == 0, M == 3 -> D = D + 1
6. 1/10 -> D == 0, M == 1 -> sum = sum + 1*10^3 == 1000
7. D == 0, sum == 1000
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.