C++で最大K個のセットビットを持つX未満の最大数を求める方法
このチュートリアルでは、与えられた整数 x 以下で、セットビット(2進数表記において1になっているビット)の数が最大 k 個となる最大の数を求めるプログラムをC++で作成します。
問題のポイント
セットビットとは、数値を2進数で表したときに値が1となっているビットのことです。例えば、65は2進数で「1000001」と表されるため、セットビットは2個あります。
解き方の手順
- 整数 x と k を初期化します。
- x のセットビットの数を求めます。
- セットビット数から k を引いた回数だけループを実行します。
- 各ループで、x の値を
x & (x - 1)で更新します。
- 各ループで、x の値を
- 最終的な x の値を返します。
x & (x - 1) という演算は、x の最下位にあるセットビットを0にする有名なビット操作テクニックです。この操作を繰り返し適用することで、セットビットの数を1つずつ減らし、条件を満たす最大の数を効率的に求めることができます。
実装例
それでは、実際のコードを見てみましょう。
#include <bits/stdc++.h>
using namespace std;
int largestNumberWithKBits(int x, int k) {
int set_bit_count = __builtin_popcount(x);
if (set_bit_count <= k) {
return x;
}
int diff = set_bit_count - k;
for (int i = 0; i < diff; i++) {
x &= (x - 1);
}
return x;
}
int main() {
int x = 65, k = 2;
cout << largestNumberWithKBits(x, k) << endl;
return 0;
}
出力結果
上記のコードを実行すると、次のような結果が得られます。
65
この例では、65(2進数:1000001)のセットビットは2個であり、k = 2 以下の条件をすでに満たしているため、そのまま65が返されます。もし x のセットビット数が k を超えていた場合は、超過分だけ下位のセットビットが順にクリアされます。
まとめ
本チュートリアルでは、GCC拡張の __builtin_popcount 関数でセットビット数を取得し、x & (x - 1) の操作を繰り返すことで、セットビットが最大k個となる最大の数を効率よく求める方法を学びました。チュートリアルの内容についてご不明な点がある場合は、コメント欄でお気軽にお知らせください。
-
C++で整数のビットが交互パターン(1010…)になっているか判定する方法
整数 n が与えられたとき、その2進表現が「101010…」のように0と1が交互に並ぶパターン(交互パターン)になっているかどうかを判定する方法を紹介します。 基本的なアプローチ 考え方は非常にシンプルです。数値を2進数として下位ビットから順に調べていき、隣り合う2つのビットが同じ値だった時点で false を返します。最後まで隣接ビットが一度も一致しなければ、その数は交互パターンを持っていると判断できます。 n % 2 で最下位ビットを取得し、直前のビット(previous)として保存する n / 2 で数値を1ビット右にずらす 新しい最下位ビット(current)と直前のビットを比較
-
C++でセットビット数に基づいて配列をソートする方法
今回は、配列を「セットビット」の数に基づいてソートするという興味深い問題を取り上げます。セットビットとは、数値を2進数で表したときに「1」となっているビットのことです。セットビット数が多い要素ほど、少ない要素よりも前に配置されるように並べ替えます。例として、12・15・7 という3つの数値を考えてみましょう。それぞれの2進数表現とセットビット数は次のとおりです。1100 (12) → セットビット数 21111 (15) → セットビット数 40111 (7) → セットビット数 3これをセットビット数の降順でソートすると、結果は以下のようになります。1111, 0111, 1100 (つま