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

C++でグレイコード(Gray Code)を生成するアルゴリズムと実装例

グレイコード(Gray Code)とは、隣り合う2つの値が必ず1ビットだけ異なるという性質を持つ二進数体系のことです。本記事では、コードのビット数を表す非負整数 n が与えられたときに、グレイコードの列を出力する方法を解説します。グレイコードの列は必ず 0 から始まる必要があります。

例えば、入力が 2 の場合、出力は [0, 1, 3, 2] となります。これは、0 のグレイコードが 00、1 が 01、2 が 11、3 が 10 であるためです。隣接する値同士を比較すると、それぞれ1ビットしか変わっていないことが確認できます。

解法のアプローチ

この問題は、以下の手順で解くことができます。

  • 結果を格納するための配列 ans を用意します。
  • 各数値についてグレイコードを求め、ans 配列へ順番に追加していきます。
  • 数値をグレイコードへ変換するには、元の数値と、それを1ビット右にシフトした値との排他的論理和(XOR)を計算します。

グレイコードへの変換は「g = i ^ (i >> 1)」という非常にシンプルな式で表されます。この変換を用いると、隣接する数値間で必ず1ビットのみが変化することが数学的に保証されるため、複雑な再帰処理や条件分岐は一切不要です。

C++による実装例

理解を深めるために、以下のC++コードを見てみましょう。

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

void print_vector(vector<int> v){
    cout << "[";
    for(int i = 0; i<v.size(); i++){
        cout << v[i] << ", ";
    }
    cout << "]"<<endl;
}

class Solution {
public:
    vector<int> grayCode(int n) {
        vector<int> ans;
        for(int i = 0; i<1<<n; i++){
            ans.push_back(i^(i>>1));
        }
        return ans;
    }
};

main(){
    Solution ob;
    print_vector(ob.grayCode(4));
}

入力

4

出力

[0, 1, 3, 2, 6, 7, 5, 4, 12, 13, 15, 14, 10, 11, 9, 8]

処理のポイント

この実装では、ループを 0 から 2^n - 1 まで回し、各インデックス i に対して i ^ (i >> 1) を計算しています。ビットシフトとXORだけで構成されているため、処理は極めて高速で、計算量は O(2^n) となります。

また、出力されたリストを2進数で確認すると、隣接する要素間で常に1ビットだけが反転していることが分かります。この性質により、グレイコードはデジタル通信やエラー検出、ロータリーエンコーダなど、誤読を防ぎたい場面で広く活用されています。

  1. C++で解く対角トラバースII:リストのリストを対角順に出力する方法

    問題の概要 「リストのリスト」である nums が与えられたとき、そのすべての要素を対角順(ダイアゴナルオーダー)に並べて出力するのがこの問題の目的です。 たとえば、次のような行ごとに長さの異なる配列(ジャグ配列)が入力として与えられた場合を考えてみましょう。 このとき、期待される出力は次のとおりです。 [1, 6, 2, 8, 7, 3, 9, 4, 12, 10, 5, 13, 11, 14, 15, 16] 解法のアプローチ この問題は、各要素を「値と座標のセット」として一旦記録し、対角線ごとの順序になるようにソートし直すことで解けます。具体的な手順は以下の通りです。 結果を格納す

  2. C++でプロセスを強制終了する方法:BFSを使った実装解説

    n個のプロセスがあると仮定します。各プロセスには、PID(プロセスID)と呼ばれる一意の識別子が割り当てられており、さらにPPID(親プロセスID)も持っています。各プロセスが持てる親プロセスは1つだけですが、子プロセスは1つでも複数でも構いません。これはまさに木構造と同じ形です。PPIDが0になるプロセスは1つだけであり、それはそのプロセスに親が存在しないことを意味します。また、すべてのPIDは一意な正の整数です。問題の概要ここでは、2つの整数リストを使ってプロセスの一覧を表現します。1つ目のリストには各プロセスのPIDが含まれ、2つ目のリストにはそれに対応するPPIDが含まれます。このとき