Дано ціле число N. Яке найменше ціле число більше N, яке має лише 0 або 1 як його цифри?


15

У мене є ціле число N. Я повинен знайти найменше ціле число більше N, яке не містить жодної цифри, крім 0 або 1. Наприклад: Якщо 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, покладіть нуль і перенесіть 1. Повторіть для кожної позиції
Sembei Norimaki

1
Це описує подібну проблему. Допомагає, можливо,
TomBombadil

Чи Nдозволено негатив ? Також це важко, оскільки ви ризикуєте переповнити тип. Які межі N?
Вірсавія

1
@SembeiNorimaki: це неправильно. Залишатиметься незмінним число, яке складається виключно з 0 і 1. І є інші відмови.
Ів Дауст

1
@SembeiNorimaki: Я сказав, що є й інші невдачі. Вони залишаються, як ваш метод неправильний. Спробуйте цілі числа від 1 до 50, і ви знайдете помилки. Errare humanum, perseverare diabolicum.
Ів Дауст

Відповіді:


20
  1. Приріст N,

  2. Починаючи зліва, скануйте, доки не знайдете цифру вище 1. Збільште часткове число перед ним і нуль решту.

Напр

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 і суфіксом, що настає після. Треба замінити першу цифру суфікса на нуль і встановити більший префікс. Найменший префікс, який підходить, - це поточний префікс плюс один. І найменший суфікс, який підходить, - це всі нулі.


Оновлення:

Я забув вказати, що префікс потрібно збільшувати як двійкове число , інакше можуть з’явитися заборонені цифри.


7

Іншою можливістю буде наступна:

  • Ви починаєте з найбільшого десяткового числа типу "1111111 ... 1111", підтримуваного використовуваним типом даних

    Алгоритм передбачає, що вхід менший за це число; інакше доведеться використовувати інший тип даних.

    Приклад: при використанні long longви починаєте з числа 1111111111111111111.

  • Потім обробіть кожну десяткову цифру зліва направо:
    • Спробуйте змінити цифру з 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 ++):

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. Розгорніть результат, ведучи до нуля
  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

Ви отримуєте результат у десятковому форматі.


II. Ділення.

  1. Збільшити N на 1
  2. Встановіть суму 0
  3. Розділіть результат на 10, щоб отримати частини D (D) та mod (M)
  4. Перевірте M
    (a), якщо M перевищує 1, тоді збільшуйте D
    (b), інакше збільште суму на M * 10 k , де k - номер поточної ітерації (починаючи з 0)
  5. Повторюйте кроки 3,4, поки D не дорівнює 0

Приклад 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.