C++でシャッフルされた配列から欠落している数値を見つける方法
2つの配列AとBがあるとします。配列Aにはn個の要素が含まれており、配列BにはAのすべての要素が含まれていますが、要素の順序がシャッフルされており、そのうち1つの要素が削除されています。この削除された要素(欠落している数値)を見つける必要があります。
例えば、A = [4, 8, 1, 3, 7]、B = [7, 4, 3, 1] の場合、配列Bには「8」が存在しないため、出力は8となります。
XOR(排他的論理和)を使った解法
この問題は、XORの性質を利用することで効率的に解くことができます。各要素は配列Aと配列Bにそれぞれ1回ずつ、合計2回出現しますが、欠落している要素だけは配列Aにしか存在しません。
XORには以下の重要な性質があります。
- x XOR x = 0:同じ値を2回XORすると0になる
- x XOR 0 = x:0とのXORは元の値を保つ
- XORは順序に依存しない(結合律・交換律が成り立つ)
そのため、両方の配列のすべての要素に対してXORを計算すると、2回出現する要素はすべて打ち消されて0になり、最終的に残るのは1回しか出現しない欠落している数値となります。
アルゴリズムの手順
- 結果を格納する変数を0で初期化します。
- 配列Aのすべての要素を順にXORします。
- 配列Bのすべての要素を順にXORします。
- 最終的な結果が欠落している数値となります。
実装例
#include<iostream>
using namespace std;
int FindMissingElement(int A[], int B[], int n) {
int missing = 0;
for (int i = 0; i < n; i++)
missing = missing ^ A[i];
for (int i = 0; i < n - 1; i++)
missing = missing ^ B[i];
return missing;
}
int main() {
int A[] = {4, 8, 1, 3, 7};
int B[] = {7, 4, 3, 1};
int n = sizeof(A) / sizeof(A[0]);
cout << "Missing element: " << FindMissingElement(A, B, n);
}出力
Missing element: 8
計算量の分析
- 時間計算量:O(n) — 各配列を1回ずつ走査するだけです。
- 空間計算量:O(1) — 追加のメモリは定数個の変数のみで済みます。
この方法は、ハッシュマップやソートを使用するアプローチと比べて、追加メモリをほとんど消費せず、かつ線形時間で処理できるため非常に効率的です。数値のオーバーフローも発生しないため、大きな値を扱う場合でも安全に動作します。
-
C++で配列内の数値の頻度(出現回数)を求める方法
配列に n 個の異なる要素が格納されているとします。この配列の中から、特定の要素が何回出現するか(頻度)を調べたい場合があります。例えば、配列 A = [5, 12, 26, 5, 3, 4, 15, 5, 8, 4] の中で「5」の頻度を調べると、答えは 3 になります。アルゴリズムの考え方この問題は、次の手順で解くことができます。1. 配列を左端から順に走査します。2. 現在の要素が調べたい数値と一致したら、カウンターを1つ増やします。3. 一致しない場合は、そのまま次の要素へ進みます。4. 配列の最後まで走査したら、カウンターの値が頻度となります。このアルゴリズムの計算量は O(n) で
-
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か