C++で2進数から1ビットを削除して最大値を求める方法
問題の概要
本記事では、与えられた2進数から1ビットを削除し、残りのビットで表される数が他のすべての選択肢の中で最大になるようにする問題を解説します。
入力 : N = 1011 出力: 111 説明: 1ビットを削除する必要があります。「0」のビットを削除すると、いずれかの「1」のビットを削除した場合よりも大きな数になります。111 > 101, 011 入力: 111 出力: 11 説明: すべてのビットが「1」なので、どのビットを削除しても結果は同じになります。
解決アプローチ
全探索(ブルートフォース)法
最も単純な方法は、各ビットを1つずつ削除してみて、それぞれの結果を比較し、最大の結果を得るという全探索です。この方法でも確かに最大値は求まりますが、計算量が多くなります。
しかし、この問題には効率的なアプローチが存在します。それは「最も影響の少ないビット」を削除するという考え方です。
効率的なアプローチ
効率的なアプローチでは、結果の数値への影響が最小となるビットを削除します。手順は以下の通りです。
まず、右側からビットを走査します。
「0」を探し、最初に見つかった時点でそれを削除します。
「0」が見つからなかった場合(すべてのビットが「1」の場合)は、任意のビットを削除します。
実装例
効率的なアプローチのC++コード
#include <bits/stdc++.h>
using namespace std;
int main(){
string str = "1011";
bool flag = false;
int n = str.length();
// 結果を格納する新しい配列を初期化
char res[n - 1];
int j = 0;
// 2進数を先頭から走査
for (int i = 0; j < n - 1; i++) {
// 「0」が見つかった場合はスキップ
if (str[i] == '0' && flag == false) {
flag = true;
continue;
}
else
res[j++] = str[i];
}
// 結果の文字列を出力
cout << "Maximum number: " << res;
return 0;
}実行結果
Maximum number: 111
コードの解説
フラグ変数(flag)を使用することで、削除される「0」は1つだけであることを保証しています。
結果の数値を格納するために、文字型配列resを初期化しています。
ループはn-1回まで実行されます。これは、元の数より1つ少ない要素を格納する必要があるためです。
まとめ
本チュートリアルでは、2進数から1ビットを削除した後に得られる最大の数を求める問題について解説しました。全探索と効率的なアプローチの2つの解法を取り上げ、その違いを確認しました。
また、C++での実装コードを紹介しましたが、同じロジックはC、Java、Pythonなど他の言語でも同様に実装できます。本チュートリアルが皆さんの学習に役立てば幸いです。
-
C++でバイナリ文字列から部分文字列「010」を削除する最小ステップ数を求める方法
問題概要バイナリ文字列が与えられたとき、その文字列から部分文字列「010」を削除するために必要な最小のステップ数を求めるのが課題です。ここでいう1ステップとは、文字列内の任意の1文字を「0」から「1」へ(またはその逆へ)変更する操作を指します。例入力文字列が「010010」の場合、必要なステップ数は2です。最初の「0」を「1」に変更します。文字列は「110010」になります。最後の「0」を「1」に変更します。最終的な文字列は「110011」になり、「010」というパターンが完全に消えます。アルゴリズム1. 文字列をインデックス0からn-2まで走査する 2. 連続する3文字が「0」「1」「0」の
-
C++で数値の最上位セットビット(MSB)の値を求める方法
この記事では、与えられた数値に対して、最上位セットビット(MSB:Most Significant Bit)の値を求める方法を解説します。MSBの値は必ず2のべき乗になります。例えば、数値が10であれば、MSBの値は8です。手順としては、まずMSBが何番目のビットに立っているか(位置k)を求め、その位置にセットビットが立った数値、すなわち 2k を計算します。実装例以下のC++コードでは、log2 関数でMSBの位置を求め、pow 関数で2のべき乗を計算しています。#include<iostream> #include<cmath> using namespace st