C++でセットビットが1つ多い次に大きい整数を求める方法
問題概要
ある数値 n が与えられたとき、2進表現におけるセットビット(1になっているビット)の数が n より1つ多く、かつ n より大きい数値を見つける必要があります。
なお、2進表現における「1」のビットはセットビットと呼ばれます。
具体例を見てみましょう。
入力
124
出力
125
124 の2進表現は 1111100 で、セットビットは5個です。一方、125 の2進表現は 1111101 で、セットビットは6個あります。つまり 125 は、「124 より大きく、かつセットビットが1つ多い」という条件を満たす整数だというわけです。
アルゴリズム
- 数値 n を初期化します。
- セットビットの個数を数える関数を作成します。
- 反復用の変数を n + 1 で初期化します。
- 無限ループを作成します。
- n より大きい各数値について、セットビット数を順番に調べます。
- 条件を満たす数値が見つかった時点で、その数値を返します。
C++での実装例
以下は、上記アルゴリズムをC++で実装したコードです。
#include <bits/stdc++.h>
using namespace std;
int getSetBitsCount(int n) {
int count = 0;
while (n) {
if (n % 2 == 1) {
count += 1;
}
n /= 2;
}
return count;
}
int getNextGreaterElementWithOneMoreSetBit(int n) {
int setBitsCount = getSetBitsCount(n);
int i = n + 1;
while (true) {
if (setBitsCount + 1 == getSetBitsCount(i)) {
return i;
}
i += 1;
}
}
int main() {
int n = 124;
cout << getNextGreaterElementWithOneMoreSetBit(n) << endl;
return 0;
}
実行結果
上記のコードを実行すると、以下の出力が得られます。
125
補足:計算量について
この実装は非常にシンプルで理解しやすい反面、答えが遠くにある場合は反復回数が増え、時間計算量が大きくなる可能性があります。ビット演算を活用すれば、より効率的に解を求めることも可能です。まずは本記事のような素直な実装でロジックをしっかり理解し、その後ビット操作による最適化に挑戦するのがおすすめです。
-
C++で整数のビットが交互パターン(1010…)になっているか判定する方法
整数 n が与えられたとき、その2進表現が「101010…」のように0と1が交互に並ぶパターン(交互パターン)になっているかどうかを判定する方法を紹介します。 基本的なアプローチ 考え方は非常にシンプルです。数値を2進数として下位ビットから順に調べていき、隣り合う2つのビットが同じ値だった時点で false を返します。最後まで隣接ビットが一度も一致しなければ、その数は交互パターンを持っていると判断できます。 n % 2 で最下位ビットを取得し、直前のビット(previous)として保存する n / 2 で数値を1ビット右にずらす 新しい最下位ビット(current)と直前のビットを比較
-
C++で整数の1の補数(nビット)を求める方法
1の補数とは本記事では、整数の「1の補数」を求める方法について解説します。C++には補数演算子(~)が用意されており、これを使えば非常に高速に補数を計算できます。ただし、この演算子は32ビット(4バイト)全体に対して補数を求めてしまうため、ここでは「与えられた数値のビット数分だけの補数」を取得する方法を考えます。例として、22という数値を取り上げます。22の2進表現は「10110」であり、その1の補数は「01001」、つまり10進数の9になります。では、この値はどのようにして求めればよいのでしょうか。求め方の手順まず、対象の数値のビット数を求めます。この値をcとします(22の場合、c = 5)