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

C++で2つの配列の共通要素の合計を求める方法

この問題では、すべての要素が互いに異なる(ユニークな値を持つ)2つの配列 arr1[] と arr2[] が与えられます。私たちのタスクは、2つの配列に共通して存在する要素の合計(オーバーラップサム)を求めることです。

問題の概要

両方の配列に出現する要素をすべて見つけ、その合計値を返します。共通要素は各配列に1つずつ存在するため、1つの共通要素につき値を2回加算することになります。

具体例で理解しよう

入力:

arr1[] = {5, 4, 9, 2}, arr2[] = {6, 3, 9, 4}

出力:

26

解説

両方の配列に存在する要素は「9」と「4」です。
合計は 9 + 9 + 4 + 4 = 26 となります。

解決アプローチ

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

最もシンプルな方法は、片方の配列(例えば arr1[])を走査し、各要素についてもう一方の配列内に一致する値が存在するかどうかを確認することです。一致する要素が見つかった場合は、その値を合計に2回加算します。

しかし、この方法ではループの入れ子構造が必要となるため、時間計算量は O(N²) となり、配列サイズが大きくなると非効率です。

方法2:ハッシュを活用した効率的な手法

より効率的な解決策としてハッシュテーブル(unordered_map)を使用する方法があります。手順は以下の通りです。

  1. ハッシュテーブルを作成し、両方の配列の要素を格納しながら各要素の出現回数(頻度)を記録します。
  2. 走査後、出現回数が2になっている要素(=両方の配列に存在する要素)のみを取り出して合計します。
  3. 合計値を2倍して返します。

このアプローチにより、時間計算量は O(N) まで削減できます。

実装例

以下は、上記のソリューションの動作を示すC++プログラムです。

#include <bits/stdc++.h>
using namespace std;
int findCommonValSum(int A[], int B[], int n){
    unordered_map<int,int> hashTable;
    for(int i=0;i<n;i++){
        if(hashTable.find(A[i])==hashTable.end())
            hashTable.insert(make_pair(A[i],1));
        else
            hashTable[A[i]]++;

        if(hashTable.find(B[i])==hashTable.end())
            hashTable.insert(make_pair(B[i],1));
        else
            hashTable[B[i]]++;
    }
    int commSum = 0;
    for(auto itr = hashTable.begin(); itr!=hashTable.end(); itr++){
        if((itr->second)==2){
            commSum += (itr->first);
        }
    }
    return (commSum*2);
}
int main(){
    int A[] = { 5, 4, 9, 2 };
    int B[] = { 6, 3, 9, 4 };
    int n = sizeof(A) / sizeof(A[0]);
    cout<<"The sum of common values in the array are "<<findCommonValSum(A, B, n);
    return 0;
}

出力結果

The sum of common values in the array are 26

まとめ

2つの配列の共通要素の合計を求める問題は、ハッシュテーブルを活用することで O(N) の時間計算量で効率的に解くことができます。要素の頻度を記録し、出現回数が2の要素だけを集めて合計を2倍するというシンプルな発想がポイントです。

  1. C++でN階乗の合計の下2桁を求める方法

    本記事では、1!からN!までの階乗の合計について、その下2桁(一の位と十の位)を求める方法を解説します。例えば N = 4 の場合、1! + 2! + 3! + 4! = 33 となるため、一の位は「3」、十の位は「3」であり、結果は「33」となります。この問題には重要な性質があります。N が 5 より大きい場合、その階乗の一の位は必ず 0 になるため、6! 以降の項は一の位に一切影響を与えません。同様に、N が 10 以上になると十の位も 0 のまま変化しなくなります。したがって、N = 10 以上では結果は常に「13」で固定されます。実際に N = 1 から 10 までの階乗の値を表に整理

  2. 二分探索(分割統治)アプローチで最大部分配列の合計を求めるC++プログラム

    二分探索は、計算量 O(log n) と非常に高速な探索アルゴリズムで、「分割統治法(divide and conquer)」という原理に基づいて動作します。このアルゴリズムが正しく機能するためには、対象となるデータ集合があらかじめソート済みである必要があります。 二分探索では、データ集合の中央にある要素と目的の要素を比較しながら特定の項目を探します。一致すればそのインデックスを返し、中央の要素の方が大きければ中央より左側の部分配列を、そうでなければ右側の部分配列を探索します。この処理を部分配列に対して繰り返し、探索範囲がゼロになるまで続けます。 本記事で紹介するのは、この分割統治の考え方を応