バイナリ文字列を交互文字列にするための最小フリップ回数をC++で求める方法
バイナリ文字列「10011」が与えられたとします。これを交互文字列(0と1が交互に並んだ文字列)にするためには、最小で2文字をフリップして「10101」にする必要があります。
交互文字列には2つのパターンが考えられます。「0」で始まるパターンと「1」で始まるパターンです。そこで、両方のパターンについて必要なフリップ回数をそれぞれカウントし、そのうちの最小値を返します。具体的な例を見てみましょう。
入力
binary = "10011"
出力
2
文字列を「0」で始まる交互文字列にする場合は3回のフリップが必要ですが、「1」で始まる場合は2回のフリップで済みます。したがって、最小値は2となります。
アルゴリズム
- バイナリ文字列を初期化します。
- 「1」で始まる交互文字列にするために必要なフリップ回数をカウントします。
- 同様に、「0」で始まる交互文字列にするために必要なフリップ回数をカウントします。
- 上記2つの結果から最小値を求めます。
- 最小値を出力します。
実装
以下は、上記のアルゴリズムをC++で実装したコードです。
#include <bits/stdc++.h>
using namespace std;
char flip(char binaryDigit) {
return binaryDigit == '0' ? '1' : '0';
}
int getFlipCountToAlternateString(string binary, char expected) {
int flipCount = 0;
for (int i = 0; i < binary.length(); i++) {
if (binary[i] != expected) {
flipCount++;
}
expected = flip(expected);
}
return flipCount;
}
int main() {
string binary = "10011";
cout << min(getFlipCountToAlternateString(binary, '0'), getFlipCountToAlternateString(binary, '1')) << endl;
return 0;
}出力
上記のコードを実行すると、次の結果が得られます。
2
このアルゴリズムの計算量は、文字列の長さをNとするとO(N)であり、非常に効率的です。各文字について期待される文字と比較し、一致しない場合はフリップ回数をインクリメントするだけなので、実装もシンプルです。
-
C++でバイナリ行列をゼロ行列に変換するための最小反転回数を求める方法
m × n のバイナリ行列(0 と 1 のみで構成された行列)mat が与えられます。1 ステップごとに、任意のセルを 1 つ選び、そのセルのビットと、存在する場合は上下左右 4 つの隣接セルのビットをすべて同時に反転することができます。mat をゼロ行列(全要素が 0 の行列)へ変換するために必要な最小ステップ数を求めてください。解が存在しない場合は -1 を返します。 たとえば、入力が [[0,0], [0,1]] の場合、変換の過程は次のようになります。 この場合、3 ステップが必要となるため、出力は 3 になります。 解き方のアプローチ:BFS(幅優先探索)とビットマスク この問
-
C++でk個のセットビットを持つ数を最大化するために必要な最小フリップ回数
問題文2つの整数 n と k が与えられます。n のビットを反転(フリップ)して、結果の数がちょうど k 個のセットビット(値が1のビット)を持ち、かつ取り得る最大の数になるようにするために必要な、最小のフリップ回数を求めてください。なお、入力は「k が n のビット数より小さい」という条件を満たす必要があります。例n = 9、k = 2 とします。9 の2進表現は 1001 であり、4ビットで構成されています。4桁の2進数の中でセットビットが2個となる最大の数は 1100、すなわち10進数の 12 です。1001 を 1100 に変換するには、2ビットを反転する必要があります。アルゴリズム1