Étant donné un entier N. Quel est le plus petit entier supérieur à N qui n'a que 0 ou 1 comme chiffres?

15

J'ai un entier N. Je dois trouver le plus petit entier supérieur à N qui ne contient aucun chiffre autre que 0 ou 1. Par exemple: Si N = 12alors la réponse est 100. J'ai codé une approche par force brute en 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;
        }
    }
}

Le problème est que mon approche est trop lente. Je pense qu'il existe une approche très efficace pour résoudre ce problème. Comment puis-je résoudre ce problème efficacement?

Yaseen Mollik
la source
4
Commencez par les unités. Si le chiffre est différent de 0 ou 1, mettez un zéro et effectuez 1. Répétez pour chaque position
Sembei Norimaki
1
Cela décrit un problème similaire. Aide peut
TomBombadil
Le négatif est-il Nautorisé? En outre, cela est difficile car vous risquez de déborder votre type. Quelles sont les limites N?
Bathsheba
1
@SembeiNorimaki: c'est faux. Il restera inchangé un nombre exclusivement composé de 0 et 1. Et il y a d'autres échecs.
Yves Daoust
1
@SembeiNorimaki: J'ai dit qu'il y avait d'autres échecs. Ils restent, car votre méthode est fausse. Essayez les entiers de 1 à 50 et vous trouverez des erreurs. Errare humanum, perseverare diabolicum.
Yves Daoust

Réponses:

20
  1. Incrément N,

  2. En partant de la gauche, scannez jusqu'à ce que vous trouviez un chiffre au-dessus de 1. Incrémentez le nombre partiel avant lui et mettez à zéro le reste.

Par exemple

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

Preuve:

Le nombre demandé doit être au moins N + 1, c'est pourquoi nous incrémentons. Nous recherchons maintenant un nombre supérieur ou égal.

Appelons le préfixe les premiers chiffres 0/1 et le suffixe ce qui vient après. Nous devons remplacer le premier chiffre du suffixe par un zéro et définir un préfixe plus grand. Le plus petit préfixe qui convient est le préfixe actuel plus un. Et le plus petit suffixe qui convient est tous les zéros.


Mise à jour:

J'ai oublié de préciser que le préfixe doit être incrémenté sous forme de nombre binaire , sinon des chiffres interdits pourraient apparaître.

Yves Daoust
la source
7

Une autre possibilité serait la suivante:

  • Vous commencez avec le plus grand nombre décimal du type "1111111 ... 1111" pris en charge par le type de données utilisé

    L'algorithme suppose que l'entrée est inférieure à ce nombre; sinon, vous devrez utiliser un autre type de données.

    Exemple: lorsque vous utilisez long long, vous commencez par le nombre1111111111111111111 .

  • Ensuite, traitez chaque chiffre décimal de gauche à droite:
    • Essayez de changer le chiffre de 1 à 0.
    • Si le résultat est toujours supérieur à votre saisie, effectuez la modification (changez le chiffre en 0).
    • Sinon, le chiffre reste 1.

Exemple

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

Preuve de correction:

Nous traitons chiffre par chiffre dans cet algorithme. À chaque étape, il y a des chiffres dont la valeur est déjà connue et des chiffres dont les valeurs ne sont pas encore connues.

À chaque étape, nous sondons le chiffre inconnu le plus à gauche.

Nous avons mis ce chiffre à "0" et tous les autres chiffres inconnus à "1". Étant donné que le chiffre à sonder est le plus important des chiffres inconnus, le nombre résultant est le plus grand nombre possible, ce chiffre étant un "0". Si ce nombre est inférieur ou égal à l'entrée, le chiffre sondé doit être un "1".

D'un autre côté, le nombre résultant est plus petit que tous les nombres possibles où le chiffre sondé est un "1". Si le nombre résultant est supérieur à l'entrée, le chiffre doit être "0".

Cela signifie que nous pouvons calculer un chiffre à chaque étape.

Code C

(Le code C devrait également fonctionner sous 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 ...
Martin Rosenau
la source
3

Permettez-moi de suggérer quelques alternatives.

I. Incrémentation. Considérez cela comme une modification de la méthode @YvesDaoust.

  1. Augmente N de 1
  2. Développer le résultat avec un zéro en tête
  3. Passez du dernier au deuxième chiffre
    (a) s'il est inférieur à 2, puis laissez tout tel
    quel (b) sinon mettez-le à 0 et augmentez le précédent
  4. Répétez les étapes 3a, b

Exemples:

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

Vous obtenez le résultat au format décimal.


II. Partage.

  1. Augmente N de 1
  2. Définir la somme à 0
  3. Divisez le résultat par 10 pour obtenir les parties div (D) et mod (M)
  4. Cochez M
    (a) si M dépasse 1 puis augmentez D
    (b) sinon augmentez la somme de M * 10 k , où k est le numéro d'itération actuel (commençant par 0)
  5. Répétez les étapes 3,4 jusqu'à ce que D soit 0

Exemple 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

Exemple 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

Exemple 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

Exemple 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
Crâne vieux
la source