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

C++で「ペアの合計値が配列内にすでに存在する」ペアを見つける方法

この記事では、N個の整数からなる配列 arr[] が与えられたとき、2つの要素の合計値がその配列内にすでに存在するようなペアを見つけるアルゴリズムを解説します。つまり、「ペアの合計値 = 配列内のいずれかの値」となる組み合わせをすべて抽出するのが目的です。

問題の理解:入力例と出力例

具体的な例を使って問題を確認しましょう。

入力

arr[] = {1, 2, 4, 6, 7}

出力

(1, 6), (2, 4)

説明

  • ペア (1, 6) の場合:合計値は 7 であり、7 は配列内に存在します。
  • ペア (2, 4) の場合:合計値は 6 であり、6 も配列内に存在します。

解法アプローチ1: 全探索(ブルートフォース)

最もシンプルな解決策は、配列の要素から作成できるすべてのペアを列挙する方法です。各ペアについて合計値を計算し、その値が配列内に存在するかどうかを線形探索で確認します。存在していれば、そのペアを出力します。

あわせて、見つかったペアの数を記録するカウンターを用意し、処理終了時にカウントが 0 であれば「該当するペアは見つかりませんでした」と表示するようにします。

この解法の動作を示すプログラムは以下の通りです。

実装例

#include <iostream>
using namespace std;
void findSumPairsArr(int arr[], int n){
    int pairCount = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            for (int k = 0; k < n; k++) {
                if (arr[i] + arr[j] == arr[k]) {
                    cout<<"( "<<arr[i]<<", "<<arr[j]<<" ), sum = "<<(arr[i] + arr[j])<<"\n";
                    pairCount++;
                }
            }
        }
    }
    if (!pairCount)
        cout<<"No Such Pairs found !";
}
int main() {
    int arr[] = { 1, 2, 4, 6, 7 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout<<"Pairs in array whose sum already exists in array : \n";
    findSumPairsArr(arr, n);
    return 0;
}

出力

配列内で合計値がすでに存在するペア −

( 1, 6 ), sum = 7
( 2, 4 ), sum = 6

この方法では、ペアの生成に2重ループ、さらに合計値の探索にもループが必要なため、時間計算量は O(N³) となります。データサイズが大きくなると非効率になる点に注意しましょう。

解法アプローチ2: ハッシュテーブルを使った効率的な解法

より効果的なアプローチとして、ハッシュテーブルを活用する方法があります。まず配列のすべての要素をハッシュテーブルに挿入しておきます。その後、すべてのペアをチェックして合計値を計算し、その値がハッシュテーブルに存在するかどうかを平均 O(1) の時間で確認できます。

C++ では、STL の unordered_set を使うことでハッシュテーブルを簡単に実装できます。こちらも同様に、見つかったペアの数をカウントし、pairCount が 0 の場合は「No Such Pairs found !」と表示します。

実装例

#include <bits/stdc++.h>
using namespace std;
void findSumPairsArr(int arr[], int n) {
    unordered_set<int> HT;
    for (int i = 0; i < n; i++)
        HT.insert(arr[i]);
    int pairCount = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (HT.find(arr[i] + arr[j]) != HT.end()) {
                cout<<"( "<<arr[i]<<", "<<arr[j]<<" ), sum = "
                    <<(arr[i] + arr[j])<<"\n";
                pairCount++;
            }
        }
    }
    if (!pairCount)
        cout<<"No Such Pairs found !";
}
int main() {
    int arr[] = {1, 2, 4, 6, 7 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout<<"Pairs in array whose sum already exists in array : \n";
    findSumPairsArr(arr, n);
    return 0;
}

出力

配列内で合計値がすでに存在するペア −

( 1, 6 ), sum = 7
( 2, 4 ), sum = 6

まとめ

アプローチ時間計算量空間計算量
全探索(3重ループ)O(N³)O(1)
unordered_set(ハッシュ)O(N²)O(N)

ハッシュテーブルを利用することで、合計値の存在確認が高速化され、全体の時間計算量を O(N³) から O(N²) まで改善できます。メモリを追加で消費する代わりに大幅な高速化が得られるため、実務的には unordered_set を使った手法が推奨されます。

  1. C++で配列のすべての部分集合(サブセット)の合計を求める方法

    問題の概要整数の配列が与えられたとき、その部分集合(サブセット)から作り出せるすべての異なる合計値を求め、昇順に出力する方法を解説します。この問題は、配列の要素の合計値が比較的小さい場合に、動的計画法を使って効率的に解くことができます。例として、配列 [1, 2, 3] を考えてみましょう。考えられるすべての部分集合は {}、{1}、{2}、{3}、{1, 2}、{2, 3}、{1, 3}、{1, 2, 3} であり、それぞれの合計値は 0, 1, 2, 3, 3, 5, 4, 6 となります。重複する値を取り除くと、出力は 0, 1, 2, 3, 4, 5, 6 となります。アプローチ:動的

  2. 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か