C++でN個のバイナリ文字列のビット単位OR(論理和)を計算する方法
問題の概要
この問題では、n 個のバイナリ文字列からなる配列 bin[] が与えられます。私たちの課題は、これら n 個のバイナリ文字列すべてのビット単位OR(論理和)を求めるプログラムを作成することです。
具体的には、すべての文字列に対して次のような演算を行います。
bin[0] | bin[1] | ... | bin[n-2] | bin[n-1]
それでは、具体例を使って問題を理解しましょう。
入力:
bin[] = {"1001", "11001", "010101"}出力:
011101
説明: すべてのバイナリ文字列のビット単位ORは以下のように計算されます。
(1001) | (11001) | (010101) = 011101
解決策のアプローチ
この問題を解くための手順はシンプルです。まず、最もビット数が多い(最長の)文字列を見つけます。次に、他のすべての文字列の先頭に必要な数だけ「0」を追加して長さを揃えます。その後、各桁ごとにビット単位ORを計算すれば結果が得られます。
アルゴリズムの動作を例で確認してみましょう。
bin[] = {"1101", "011010", "00111"}最長の文字列は長さ6の「011010」です。そこで、他の文字列の先頭に0を追加して長さを揃えます。
更新後の文字列:「001101」「011010」「000111」
すべての文字列のビット単位ORを求めると、次のようになります。
001101 | 011010 | 000111 = 011111
C++での実装例
上記の解決策の動作を示すプログラムは以下の通りです。
#include <bits/stdc++.h>
using namespace std;
string bitwiseOR(string* bin, int n){
string result;
int max_size = INT_MIN;
// 最長の文字列の長さを求め、各文字列を反転
for (int i = 0; i < n; i++) {
max_size = max(max_size, (int)bin[i].size());
reverse(bin[i].begin(), bin[i].end());
}
// 長さを揃えるために末尾(元の先頭)に0を追加
for (int i = 0; i < n; i++) {
string s;
for (int j = 0; j < max_size - bin[i].size(); j++) s += '0';
bin[i] = bin[i] + s;
}
// 各桁ごとにビット単位ORを計算
for (int i = 0; i < max_size; i++) {
int insertBit = 0;
for (int j = 0; j < n; j++)
insertBit = insertBit | (bin[j][i] - '0');
result += (insertBit + '0');
}
// 結果を元の順序に戻す
reverse(result.begin(), result.end());
return result;
}
int main() {
string bin[] = { "1101", "011010", "00111" };
int n = sizeof(bin) / sizeof(bin[0]);
cout<<"配列内のすべてのバイナリ文字列のビット単位ORは "<<bitwiseOR(bin, n);
return 0;
}コードのポイント
- 文字列を反転してから処理することで、桁の位置合わせが容易になります。
- 短い文字列には先頭(反転後は末尾)に「0」を補完し、すべての文字列の長さを最大長に揃えています。
- 各桁に対して全文字列のビットをOR演算し、その結果を連結して最終的な答えを構築します。
実行結果
配列内のすべてのバイナリ文字列のビット単位ORは 011111
まとめ
このように、長さの異なる複数のバイナリ文字列のビット単位ORを求める場合は、まず最長の文字列に合わせて先頭を0で埋めて長さを揃えることが重要なポイントです。この手法により、任意の個数・任意の長さのバイナリ文字列に対して効率的にOR演算を実行できます。時間計算量は O(n × L)(n は文字列の個数、L は最大長)となり、非常に効率的です。
-
C++で文字列から二分木を構築する方法
括弧と整数から構成される文字列が与えられたとき、その文字列から二分木を構築する問題を考えてみましょう。入力文字列全体が一つの二分木を表しており、整数の後に0個、1個、または2組の括弧が続く形式になっています。整数はルート(根)ノードの値を表し、各括弧のペアは同じ構造を持つ子の部分木を含んでいます。問題の例例えば、入力が 4(2(3)(1))(6(5)) のような文字列だった場合、出力は [3,2,1,4,5,6](中順走査・inorder traversal の結果)となります。解決アプローチこの問題を解くために、以下の手順に従います。再帰関数 solve() を定義します。引数として文字列
-
C++で2つの2進数文字列を加算するプログラムの書き方
2つの2進数を表す文字列が与えられたとき、それらを加算した結果を求め、その結果を2進数の文字列として返すことを考えます。2進数とは、0か1のいずれかで表現される数値のことです。2進数同士を足し合わせる際には、以下のような2進数特有の加算ルールに従う必要があります。0+0 → 0 0+1 → 1 1+0 → 1 1+1 → 0(繰り上がり1)入力例str1 = {11}, str2 = {1}出力例100入力例str1 = {110}, str2 = {1}出力例111問題を解くためのアプローチ両方の文字列を末尾(最下位桁)から走査する対応する桁の2進数同士を加算する1と1を足した場合は、その桁