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

【C++】指定された合計値となるすべてのペアを出力する方法

問題概要

この問題では、整数の配列と目標となる合計値が与えられ、その合計値と等しくなるすべての整数ペアを見つけて出力する必要があります。

具体例を使って問題を理解してみましょう。

入力: array = {1, 6, -2, 3}、sum = 4

出力: (1, 3) 、(6, -2)

つまり、指定された合計値を持つペアをすべて見つけ出すことが求められています。

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

最もシンプルな解決策は、合計値を生成する要素のペアを一つずつ確認していく方法です。配列を走査し、各要素について合計値に一致する組み合わせとなる数を探すことで実装できます。

この方法は理解しやすい反面、二重ループを使用するため時間計算量がO(n²)となり、大きな配列に対しては非効率です。

サンプルプログラム

#include <iostream>
using namespace std;
int printPairsWithSum(int arr[], int n, int sum){
    int count = 0;
    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
            if (arr[i] + arr[j] == sum)
                cout<<"[ "<<arr[i]<<", "<<arr[j]<<" ]\n";
}
int main(){
    int arr[] = {1, 6, -2, 3};
    int n = 4;
    int sum = 4;
    cout<<"Pairs with Sum "<<sum<<" are :\n";
    printPairsWithSum(arr, n, sum);
    return 0;
}

出力結果

Pairs with Sum 4 are :
[ 1, 3 ]
[ 6, -2 ]

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

上記の方法は簡単に理解できるものの、あまり効率的とは言えません。そこで有効なのがハッシュテーブルを活用するアプローチです。

手順は以下の通りです。

  1. 空のハッシュテーブルを初期化する
  2. 配列を順番に走査し、各要素に対して「合計値からその要素を引いた値(補完値)」を計算する
  3. 補完値がすでにハッシュテーブルに存在すれば、それは合計値を持つペアなので出力する
  4. 現在の要素をハッシュテーブルに登録して次へ進む

このアプローチにより、時間計算量をO(n)まで改善でき、大規模なデータでも高速に動作します。

サンプルプログラム

#include <bits/stdc++.h>
using namespace std;
void printPairsWithSum(int arr[], int n, int sum){
    unordered_map<int, int> pair;
    for (int i = 0; i < n; i++) {
        int rem = sum - arr[i];
        if (pair.find(rem) != pair.end()) {
            int count = pair[rem];
            for (int j = 0; j < count; j++)
                cout<<"["<<rem<<", "<<arr[i]<<" ]\n";
        }
        pair[arr[i]]++;
    }
}
int main(){
    int arr[] = {1, 6, -2, 3};
    int n = 4;
    int sum = 4;
    cout<<"The pair with sum is \n";
    printPairsWithSum(arr, n, sum);
    return 0;
}

出力結果

Pairs with Sum 4 are :
[ 1, 3 ]
[ 6, -2 ]

まとめ

指定された合計値を持つペアを見つけるには、全探索によるO(n²)の単純な方法と、ハッシュテーブルを用いたO(n)の効率的な方法の2つのアプローチがあります。小さな配列なら前者でも十分ですが、データサイズが大きい場合は後者のハッシュベースの手法を採用することで、大幅なパフォーマンス向上が期待できます。

  1. C++で文字列のすべての部分文字列を出力するプログラムの解説

    はじめにこの記事では、与えられた文字列からすべての部分文字列を取り出して出力するC++プログラムについて解説します。文字列(char型配列)が1つ与えられ、その文字列から生成できるすべての部分文字列を順番に画面へ表示するのが本プログラムの目的です。部分文字列とは部分文字列とは、元の文字列から連続する文字を取り出して作られる文字列のことです。例えば「abca」という文字列の場合、「a」「b」「ab」「bca」「abca」などがすべて部分文字列に該当します。長さnの文字列からは、長さ1の部分文字列がn個、長さ2のものがn-1個、長さ3のものがn-2個…と続くため、部分文字列の総数は n×(n+1)

  2. C++で指定された範囲内のすべての回文数を出力するプログラム

    このチュートリアルでは、指定された範囲内に存在するすべての回文数を見つけて出力するC++プログラムについて解説します。回文数とは、12321のように、前から読んでも後ろから読んでも同じになる数値のことです。このプログラムでは、検索対象となる数値の範囲(最小値と最大値)が与えられ、その範囲内に含まれるすべての回文数を検出して出力します。プログラムの流れ処理は大きく分けて2つのステップで構成されています。1. 回文判定関数(is_palin)引数として受け取った数値が回文かどうかを判定します。数値を1桁ずつ取り出しながら逆順に組み立て、元の数値と一致するかどうかを比較します。2. 範囲走査関数(c