整数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以外の場合は、ゼロを挿入して1を実行します。各位置について繰り返します
船平則巻

1
これは同様の問題を説明しています。たぶん助ける
TomBombadil '14

ネガティブはN許可されますか?また、型がオーバーフローするリスクがあるため、これは困難です。限界はN何ですか?
バトシェバ

1
@SembeiNorimaki:これは間違っています。0と1のみで構成された数は変更されません。その他の障害があります。
Yves Daoust

1
@SembeiNorimaki:他にも失敗があると言った。あなたの方法が間違っているので、それらは残ります。1から50までの整数を試すと、間違いが見つかります。Errare humanum、perseverare diabolicum。
Yves Daoust

回答:


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桁と呼び、その後に続くものをサフィックスと呼びます。サフィックスの最初の桁をゼロに置き換え、より大きなプレフィックスを設定する必要があります。適合する最小のプレフィックスは、現在のプレフィックスに1を加えたものです。そして、適合する最小のサフィックスはすべてゼロです。


更新:

プレフィックスを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

正当性の証明:

このアルゴリズムでは、1桁ずつ処理します。各ステップには、値が既知である数字と、まだ値が不明である数字があります。

各ステップで、左端の不明な数字を調べます。

その数字を「0」に設定し、その他すべての不明な数字を「1」に設定します。プローブされる数字は不明な数字の中で最も重要であるため、結果の数字はその数字が「0」である可能な最大の数字です。この数値が入力以下の場合、プローブされる桁は「1」でなければなりません。

一方、結果として得られる数は、プローブされる桁が「1」であるすべての可能な数よりも小さくなります。結果の数値が入力よりも大きい場合、数字は「0」でなければなりません。

これは、各ステップで1桁を計算できることを意味します。

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. 先行ゼロで結果を拡大する
  3. 下から2番目の数字に移動する
    (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をチェックしてM
    (a)が1を超えている場合はDを増やし、
    それ以外の場合は合計をM * 10 k増やします(kは現在の反復数(0から始まります))
  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.