C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++でKビット異なる配列のペア数を数える方法

はじめに

この記事では、配列内の要素ペアのうち、2進表現においてKビットだけ異なるペアの総数を求めるC++プログラムについて解説します。

具体的には、整数の配列と整数Kが与えられたとき、任意の2つの要素を比較し、異なるビットの数がちょうどK個になるペアがいくつ存在するかを計算します。

解決のアプローチ

この問題は、XOR(排他的論理和)の性質を利用することでシンプルに解けます。

  • 配列内のすべてのペア(arr[i], arr[j])について、2つの値のXORを計算します。
  • XORの結果に含まれる「1」のビット数(セットビット数)を数えます。これは2つの要素間で異なるビットの数に一致します。
  • セットビット数がKと等しければ、そのペアをカウントします。

C++での実装例

#include <bits/stdc++.h>
using namespace std;

// 2進表現におけるセットビット数を数える
int count_bit(int n){
    int count = 0;
    while (n) {
        if (n & 1)
            ++count;
        n >>= 1;
    }
    return count;
}

// Kビット異なるペアの数を数える
long long count_pair(int arr[], int n, int k) {
    long long ans = 0;
    for (int i = 0; i < n-1; ++i) {
        for (int j = i + 1; j < n; ++j) {
            int xoredNum = arr[i] ^ arr[j];
            if (k == count_bit(xoredNum))
                ++ans;
        }
    }
    return ans;
}

int main() {
    int k = 2;
    int arr[] = {2, 4, 1, 3, 1};
    int n = sizeof(arr)/sizeof(arr[0]);
    cout << "Total pairs for k = " << k << " are " << count_pair(arr, n, k) << "\n";
    return 0;
}

出力結果

5

コードの解説

count_bit関数: 引数で受け取った整数の2進表現に含まれる「1」のビット数を数えます。値を右シフトしながら、最下位ビットが1かどうかを順番に判定していきます。

count_pair関数: 二重ループで配列内のすべてのペアを走査します。各ペアのXORを計算し、そのセットビット数がKと一致した場合のみカウントを増やします。時間計算量はO(n²)です。

出力の検証: 配列{2, 4, 1, 3, 1}の2進表現はそれぞれ「10」「100」「1」「11」「1」です。たとえば2(10)と4(100)のXORは110となり、セットビット数は2のためK=2の条件を満たします。このようなペアをすべて数えると、合計5ペアになります。

まとめ

XOR演算とセットビットのカウントを組み合わせることで、Kビット異なるペアの数を簡単に求められます。ただし本手法はO(n²)の計算量となるため、要素数が非常に多い配列を扱う場合は、Trie(トライ)木などを活用した最適化手法の導入も検討するとよいでしょう。

  1. C++で配列内のab=cdとなるすべてのペア(a, b)と(c, d)を見つける方法

    配列Aが与えられたとき、その中から積が等しくなる2つのペア(a, b)と(c, d)、つまりab = cdを満たす組み合わせを見つける問題を考えます。例えば、配列A = [3, 4, 7, 1, 2, 9, 8]の場合、(4, 2)と(1, 8)というペアが条件を満たします。実際に4×2 = 8、1×8 = 8となり、積が一致していますね。この問題を効率的に解くには、ハッシュテーブル(C++ではunordered_map)を活用します。すべてのペアの積を順に計算し、同じ積がすでにハッシュテーブルに登録されているかどうかを確認することで、条件を満たすペアを検出できます。アルゴリズムの手順iを0か

  2. C++で配列内の反転数(Inversion Count)を求めるプログラムの解説

    「反転数(Inversion Count)」とは、配列を昇順にソートされた状態にするために必要な要素の入れ替え回数を表す指標です。配列がすでにソートされている場合、反転数は 0 となり、逆に配列が完全に逆順に並んでいる場合、反転数は最大値になります。この記事では、配列内の反転数を数えるC++プログラムを実際に作成しながら、その考え方と実装方法をわかりやすく解説します。反転数とは配列内の2つの要素 a[i] と a[j] について、i < j かつ a[i] > a[j] が成り立つとき、このペアを「反転(inversion)」と呼びます。配列全体に存在する反転ペアの総数が反転数です