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

C++で2つの配列の要素の和からなる集合のN番目の要素を検索する方法


この記事では、サイズmの2つのソート済み配列 arr1[] と arr2[]、および整数Nが与えられたときに、「2つの配列の要素の和から形成される集合」の中のN番目の要素を求める方法を解説します。

問題の概要

ここで扱う集合とは、arr1[i] + arr2[j](i、j < m)で表されるすべての和の値を、重複なく集めたものです。与えられたNに対して、この集合のN番目の要素の値を求めるのが課題となります。

入力例

arr1[] = {3, 1, 5} , arr2[] = {6, 2, 8} , N = 4

出力

7

説明

2つの配列の要素の和から作られる集合の要素は以下の通りです。

9 (3+6 と 1+8)、5 (3+2)、11 (3+8 と 5+6)、7 (1+6 と 5+2)、3 (1+2)、13 (5+8)

重複を除いた集合は {9, 5, 11, 7, 3, 13} となり、4番目の要素は 7 であることがわかります。

解法アプローチ

基本的な考え方はシンプルです。外側のループで arr1 の各要素を、内側のループで arr2 の各要素を走査し、すべての組み合わせについて和を計算します。計算した和を順に集合へ格納し、すでに存在する値は追加しないことで重複を排除します。すべての和を格納し終えたら、N番目の要素を取り出して返します。

アルゴリズムの手順

  1. 結果を格納するための空の集合を用意します。
  2. 二重ループで arr1[i] + arr2[j] のすべての組み合わせの和を計算します。
  3. その和がまだ集合に存在しない場合のみ、集合に追加します。
  4. すべての和を格納した後、集合のN番目の要素を返します。

C++での実装例

#include <iostream>
#include <vector>
using namespace std;

// 2つの配列の和からなる集合のN番目の要素を求める関数
int findNthItem(int arr1[], int arr2[], int m, int N) {
    vector<int> resultSet;
    // すべての組み合わせの和を計算
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < m; j++) {
            int sum = arr1[i] + arr2[j];
            // 重複チェック
            bool exists = false;
            for (int k = 0; k < (int)resultSet.size(); k++) {
                if (resultSet[k] == sum) {
                    exists = true;
                    break;
                }
            }
            if (!exists)
                resultSet.push_back(sum);
        }
    }
    // N番目の要素を返す
    if (N > 0 && N <= (int)resultSet.size())
        return resultSet[N - 1];
    return -1;
}

int main() {
    int arr1[] = {3, 1, 5};
    int arr2[] = {6, 2, 8};
    int m = sizeof(arr1) / sizeof(arr1[0]);
    int N = 4;
    cout << N << "番目の要素は " << findNthItem(arr1, arr2, m, N) << endl;
    return 0;
}

出力

4番目の要素は 7

計算量について

この解法では、m×m通りの組み合わせの和を計算し、さらに重複チェックを行うため、時間計算量は O(m²×k)(kは集合の要素数、最悪ケースでO(m³))となります。空間計算量は O(k) です。

補足:std::set を使った別解

C++の std::set を利用すれば、重複の管理をライブラリ側に任せることができ、コードをより簡潔にできます。ただし、std::set は要素を自動的に昇順ソートするため、N番目の要素は「挿入順」ではなく「昇順」で判定される点に注意してください。


  1. C++で解くTwo Sum IV ― 二分探索木(BST)が入力の場合

    問題概要 二分探索木(BST)とターゲット値が1つ与えられます。このとき、BST内に「2つの要素の和がターゲット値と等しくなる」ような組み合わせが存在するかどうかを判定するのが本問題です。 例えば、次のような木が入力として与えられた場合を考えてみましょう。 この場合、出力は True(真)となります。 解法のアプローチ この問題は、BSTを中間順(inorder)走査して昇順の配列を作り、その後「双方向ポインタ(two pointer)」を使うことで効率的に解けます。具体的には、以下の手順に従います。 値を格納するための配列 v を定義します。 関数 inorder() を定義します(引

  2. 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 までの階乗の値を表に整理