Diberikan bilangan bulat N. Apakah bilangan bulat terkecil yang lebih besar dari N yang hanya memiliki 0 atau 1 sebagai digitnya?


15

Saya memiliki bilangan bulat N. Saya harus menemukan bilangan bulat terkecil yang lebih besar dari N yang tidak mengandung angka selain 0 atau 1. Misalnya: Jika N = 12jawabannya adalah 100. Saya telah mengkodekan pendekatan brute force di 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;
        }
    }
}

Masalahnya adalah, pendekatan saya terlalu lambat. Saya percaya ada pendekatan yang sangat efisien untuk menyelesaikan ini. Bagaimana saya bisa menyelesaikan masalah ini secara efisien?


4
Mulai dengan unit. Jika digitnya selain 0 atau 1 tulis nol dan bawa 1. Ulangi untuk setiap posisi
Sembei Norimaki

1
Ini menggambarkan masalah yang sama. Membantu mungkin
TomBombadil

Apakah negatif Ndiperbolehkan? Juga, ini sulit karena Anda berisiko meluap tipe Anda. Apa batasannya N?
Batsyeba

1
@ SembeiNorimaki: ini salah. Ini akan membuat angka yang tidak berubah secara eksklusif terbuat dari 0 dan 1. Dan ada kegagalan lainnya.
Yves Daoust

1
@ SembeiNorimaki: Saya mengatakan bahwa ada beberapa kegagalan lainnya. Mereka tetap, karena metode Anda salah. Coba bilangan bulat dari 1 hingga 50 dan Anda akan menemukan kesalahan. Bersalah dengan humanum, bertahan diabolicum.
Yves Daoust

Jawaban:


20
  1. Kenaikan N,

  2. Mulai dari kiri, pindai hingga Anda menemukan angka di atas 1. Tambahkan nomor parsial sebelum dan nolkan sisanya.

Misalnya

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

Bukti:

Nomor yang diminta harus minimal N +1, ini sebabnya kami menambah. Kami sekarang mencari angka yang lebih besar atau sama.

Mari kita panggil awalan angka 0/1 awal dan akhiran apa yang terjadi setelahnya. Kita harus mengganti digit pertama akhiran dengan nol dan menetapkan awalan yang lebih besar. Awalan terkecil yang cocok adalah awalan saat ini ditambah satu. Dan sufiks terkecil yang cocok adalah semua nol.


Memperbarui:

Saya lupa menentukan bahwa awalan harus ditambah sebagai angka biner , jika tidak, angka terlarang dapat muncul.


7

Kemungkinan lain adalah yang berikut:

  • Anda mulai dengan angka desimal terbesar dari tipe "1111111 ... 1111" yang didukung oleh tipe data yang digunakan

    Algoritme mengasumsikan bahwa input lebih kecil dari angka ini; jika tidak, Anda harus menggunakan tipe data lain.

    Contoh: Saat menggunakan long long, Anda mulai dengan nomornya 1111111111111111111.

  • Kemudian proses setiap angka desimal dari kiri ke kanan:
    • Cobalah untuk mengubah digit dari 1 ke 0.
    • Jika hasilnya masih lebih besar dari input Anda, lakukan perubahan (ubah digit menjadi 0).
    • Kalau tidak digitnya tetap 1.

Contoh

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

Bukti kebenaran:

Kami memproses digit demi digit dalam algoritma ini. Di setiap langkah, ada digit yang nilainya sudah diketahui dan digit yang nilainya belum diketahui.

Di setiap langkah, kami menyelidiki digit paling tidak dikenal yang paling kiri.

Kami menetapkan digit itu ke "0" dan semua digit tidak dikenal lainnya menjadi "1". Karena digit yang akan diselidiki adalah yang paling signifikan dari digit yang tidak diketahui, angka yang dihasilkan adalah angka terbesar yang mungkin dengan digit itu menjadi "0". Jika angka ini kurang atau sama dengan input, digit yang diperiksa harus berupa "1".

Di sisi lain, angka yang dihasilkan lebih kecil dari semua angka yang mungkin di mana angka yang diselidiki adalah "1". Jika angka yang dihasilkan lebih besar dari input, digit harus "0".

Ini berarti bahwa kita dapat menghitung satu digit di setiap langkah.

Kode C

(Kode C juga harus bekerja di bawah 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

Izinkan saya menyarankan beberapa alternatif.

I. Bertambah. Anggap itu modifikasi metode @YvesDaoust.

  1. Tambah N dengan 1
  2. Perluas hasil dengan nol di depan
  3. Pergi dari yang terakhir ke digit kedua
    (a) jika kurang dari 2 maka biarkan semuanya apa adanya
    (b) jika tidak, setel ke 0 dan tambah sebelumnya
  4. Ulangi langkah 3a, b

Contoh:

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

Anda mendapatkan hasil dalam format desimal.


II Pemisah.

  1. Tambah N dengan 1
  2. Tetapkan jumlah ke 0
  3. Bagi hasil dengan 10 untuk mendapatkan bagian div (D) dan mod (M)
  4. Periksa M
    (a) jika M melebihi 1 maka tambah D
    (b) jika tidak, tambah jumlah dengan M * 10 k , di mana k adalah angka iterasi saat ini (dimulai dengan 0)
  5. Ulangi langkah 3,4 hingga D adalah 0

Contoh 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

Contoh 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

Contoh 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

Contoh 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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.