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

C++で2進表現における0と1の個数のXORを求める方法

問題概要

この問題では、ひとつの整数が与えられます。求めるのは、その数を2進表現したときに含まれる「0」の個数と「1」の個数をそれぞれカウントし、2つの値のXOR(排他的論理和)を計算することです。

具体例を使って、問題の内容を確認してみましょう。

入力

n = 9

出力

0

説明

binary = 1001
0の個数 = 2
1の個数 = 2
2 ^ 2 = 0

9を2進数で表すと「1001」になり、「0」が2個、「1」が2個含まれています。そこで 2 XOR 2 = 0 という結果が得られます。

解決のためのアプローチ

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

  1. 与えられた数値を2進数として扱い、最下位ビットから順に各ビットを調べる
  2. ビットが「0」なら0のカウントを、「1」なら1のカウントをそれぞれ増やす
  3. すべてのビットを走査し終えたら、0の個数と1の個数のXORを返す

各ビットの判定には剰余演算(n % 2)を使用します。2で割った余りが0なら偶数(最下位ビットが0)、1なら奇数(最下位ビットが1)であるため、これを繰り返すことで全ビットを効率よく走査できます。

C++による実装例

上記の解法を実装したプログラムがこちらです。

サンプルコード

#include<iostream>
using namespace std;
int countXOR10(int n) {
    int count0s = 0, count1s = 0;
    while (n){
        (n % 2 == 0) ? count0s++ : count1s++;
        n /= 2;
    }
    return (count0s ^ count1s);
}
int main() {
    int n = 21;
    cout<<"XOR of count of 0s and 1s in binary of "<<n<<" is "<<countXOR10(n);
    return 0;
}

実行結果

XOR of count of 0s and 1s in binary of 21 is 1

コードの解説

この例では n = 21 を入力としています。21を2進数で表すと「10101」であり、「0」が2個、「1」が3個含まれます。したがって 2 XOR 3 = 1 となり、出力は「1」になります。

while ループの中では、三項演算子を使って現在の最下位ビットが0か1かを判定しています。n /= 2 によって数値を右に1ビットシフトするのと同じ効果が得られ、次のビットへ処理を進めます。ループは n が0になるまで続きます。

計算量は、2進表現の桁数(ビット数)に比例するため、時間計算量は O(log n)、補助的な変数のみで済むため空間計算量は O(1) となります。非常に効率的なアルゴリズムです。

  1. C++で二分木の完全ノードを数える方法(反復法と再帰法)

    本記事では、二分木に含まれる「完全ノード(フルノード)」の数を、反復法と再帰法の2つのアプローチで求める方法を解説します。完全ノードとは、左と右の子を両方持ち、どちらの子もNULLでないノードのことです。つまり、ちょうど2つの子を持つノードのみが完全ノードとして扱われます。 二分木はデータの格納に用いられる特殊なデータ構造です。「各ノードが最大2つの子までしか持てない」という制約があり、ソート済み配列並みの高速な検索性能と、連結リスト並みの高速な挿入・削除性能を兼ね備えているのが特徴です。なお、1つ以上の子を持つ非葉ノードは「親ノード」とも呼ばれます。 二分木の基本構造は以下の通りです。

  2. C++で二分木の半ノード(ハーフノード)を数える方法【反復・再帰の両アプローチ】

    本記事では、二分木(バイナリツリー)に含まれる「半ノード(ハーフノード)」の数を、反復処理と再帰処理の2つのアプローチで求める方法を解説します。半ノードとは?半ノードとは、子を1つだけ持ち、もう片方の子がNULL(空)になっているノードのことです。なお、子をまったく持たない葉ノードは半ノードには含まれない点に注意してください。二分木はデータの格納に使われる特殊なデータ構造です。各ノードが最大2つの子を持つという制約があり、ソート済み配列並みの高速な検索と、連結リスト並みの高速な挿入・削除の両方を実現できるというメリットがあります。二分木の基本的な構造は以下の通りです。具体例入力:出力: カウン