C++でNとのビット単位AND演算により得られる数値の集合を出力する方法
この問題では、0からnまでの各整数とnをビット単位AND演算(&)したときに得られる値をすべて求め、重複なく出力します。これらの値は、nの2進表現における「1」のビットを組み合わせた部分集合(部分マスク)に相当します。
問題の例
具体例を見ながら概念を理解しましょう。
入力 : N = 4
出力 : 0 4
説明 :
0 & 4 = 0
1 & 4 = 0
2 & 4 = 0
3 & 4 = 0
4 & 4 = 4
入力 : N = 6
出力 : 0, 2, 4, 6N = 6の場合、6は2進数で「110」と表されます。0から6までの各数値と6のANDを取ると、結果は0、2、4、6の4種類のみとなります。これは「110」の各ビットを含めるか除外するかの組み合わせ、つまりnの部分マスクそのものです。
解決アプローチ
この問題を効率的に解くには、ビット演算子を活用します。nから開始し、更新式 i = (i - 1) & n を用いて降順に走査することで、AND演算の結果として現れる値だけを直接取り出せます。通常のデクリメントではなくこの式を使うことで、結果にならない数値をスキップし、無駄な計算を大幅に削減できます。
アルゴリズム
ステップ1 : 更新式 i = (i - 1) & n を使い、nから1までループする ステップ2 : 各反復で i の値を出力する ステップ3 : ループ終了後、0 を出力して終了する
実装例
上記のアルゴリズムをC++で実装したプログラムは以下の通りです。
#include <iostream>
using namespace std;
int main() {
int n = 11;
for (int i = n; i > 0; i = (i - 1) & n)
cout << i << " ";
cout << 0;
return 0;
}出力
11 10 9 8 3 2 1 0
n = 11(2進数で「1011」)の場合、11のビットの部分集合となる値が降順に出力されます。この手法の計算量は出力される部分マスクの個数に比例するため、0からnまでを全件走査する方法と比べてはるかに効率的です。
-
C++で二分木の各ノードのセットビット数を出力する方法
二分木が与えられたとき、本記事で紹介する関数は、各ノードに格納されたキーの値を2進数に変換し、その2進表現に含まれるセットビット(1)の個数を返します。例キーとして 10、3、211、140、162、100、146 を持つ二分木を考えてみましょう。各キーの2進表現とセットビット数は以下のようになります。キー2進表現セットビット数(出力)101010230011221111010011514010001100316210100010310011001003146100100103__builtin_popcount 関数についてここでは GCC が提供する組み込み関数 __builtin_pop
-
C++のビットごとのAND演算子とは?仕組みと使い方を解説
C++におけるビットごとのAND演算子(&)は、2つのオペランドの各ビットを対応する位置ごとに比較する演算子です。両方のビットが1である場合のみ、結果の該当ビットが1に設定されます。それ以外の場合は0になります。この演算子を使用する際、両方のオペランドは整数型(integral型)である必要があります。浮動小数点型には使用できません。ビットごとのANDの真理値表各ビットの組み合わせに対する結果は以下の通りです。0 & 0 → 00 & 1 → 01 & 0 → 01 & 1 → 1サンプルコード次の例では、16進数で表された2つのunsigned sho