【C++】バイナリ文字列から「01」または「10」を削除する方法を解説
「01010110011」のようなバイナリ文字列に対して、隣接する「01」または「10」を繰り返し削除することを考えます。「01」や「10」が文字列から完全になくなるまで削除を行うとき、最大で何回削除できるかを求めるのが本問題です。この記事では、C++による効率的な解法をわかりやすく解説します。
アルゴリズムのポイント
「01」または「10」を1回削除するたびに、「0」と「1」が必ず1文字ずつ減少します。つまり、削除できる最大回数は文字列に含まれる「0」の個数と「1」の個数のうち小さい方(min)に等しくなります。この性質を利用すれば、実際に削除操作をシミュレートする必要はなく、各文字の出現回数を数えるだけで答えが求まります。
実装の流れ
まず、初期文字列を宣言してその長さを取得し、それらを deleteSubstr(str, length) 関数に渡します。
string str = "01010110011"; int length = str.length(); cout << "Count of substring deletion" << deleteSubstr(str, length);
deleteSubstr(string str, int length) 関数の内部では、for ループが i が length 未満である間実行され、文字が「0」なら変数 count_0 を、「1」なら変数 count_1 をそれぞれインクリメントしていきます。そして最後に、count_0 と count_1 の小さい方の値を返り値として返します。
int deleteSubstr(string str, int length){
int count_0 = 0, count_1 = 0;
for (int i = 0; i < length; i++) {
if (str[i] == '0')
count_0++;
else
count_1++;
}
return min(count_0, count_1);
}
サンプルコード
それでは、バイナリ文字列から「01」または「10」を削除して、これらを含まない文字列にする実装全体を見てみましょう。
#include <iostream>
using namespace std;
int deleteSubstr(string str, int length){
int count_0 = 0, count_1 = 0;
for (int i = 0; i < length; i++) {
if (str[i] == '0')
count_0++;
else
count_1++;
}
return min(count_0, count_1);
}
int main(){
string str = "01010110011";
int length = str.length();
cout << "Count of substring deletion " << deleteSubstr(str, length);
return 0;
}
出力結果
上記のコードを実行すると、次のような出力が得られます。
Count of substring deletion 5
入力例「01010110011」には「0」が5個、「1」が6個含まれているため、min(5, 6) = 5 となり、削除回数は5回となります。
計算量
文字列を一度走査するだけなので、時間計算量は O(n)、追加で必要なメモリは O(1) と非常に効率的です。
-
C++で文字列から二分木を構築する方法
括弧と整数から構成される文字列が与えられたとき、その文字列から二分木を構築する問題を考えてみましょう。入力文字列全体が一つの二分木を表しており、整数の後に0個、1個、または2組の括弧が続く形式になっています。整数はルート(根)ノードの値を表し、各括弧のペアは同じ構造を持つ子の部分木を含んでいます。問題の例例えば、入力が 4(2(3)(1))(6(5)) のような文字列だった場合、出力は [3,2,1,4,5,6](中順走査・inorder traversal の結果)となります。解決アプローチこの問題を解くために、以下の手順に従います。再帰関数 solve() を定義します。引数として文字列
-
C++で二分探索(バイナリサーチ)を実装する方法を解説
二分探索(バイナリサーチ)とは二分探索(Binary Search)は、ソート済みの配列から目的の要素を効率的に見つけ出すアルゴリズムです。探索範囲を繰り返し半分に絞り込んでいくことで、先頭から順に調べる線形探索よりもはるかに高速に検索できます。具体的な手順は以下の通りです。まず配列全体を探索対象とする配列の中央にある要素と目的の値を比較する目的の値が中央の要素より大きければ上半分を、小さければ下半分を次の探索範囲とする目的の値が見つかるか、探索範囲が空になるまで手順2〜3を繰り返すこの手法により計算量は O(log n) に抑えられ、大量のデータでも高速に探索できます。C++による二分探索の