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番目の要素を取り出して返します。
アルゴリズムの手順
- 結果を格納するための空の集合を用意します。
- 二重ループで arr1[i] + arr2[j] のすべての組み合わせの和を計算します。
- その和がまだ集合に存在しない場合のみ、集合に追加します。
- すべての和を格納した後、集合の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番目の要素は「挿入順」ではなく「昇順」で判定される点に注意してください。
-
C++で解くTwo Sum IV ― 二分探索木(BST)が入力の場合
問題概要 二分探索木(BST)とターゲット値が1つ与えられます。このとき、BST内に「2つの要素の和がターゲット値と等しくなる」ような組み合わせが存在するかどうかを判定するのが本問題です。 例えば、次のような木が入力として与えられた場合を考えてみましょう。 この場合、出力は True(真)となります。 解法のアプローチ この問題は、BSTを中間順(inorder)走査して昇順の配列を作り、その後「双方向ポインタ(two pointer)」を使うことで効率的に解けます。具体的には、以下の手順に従います。 値を格納するための配列 v を定義します。 関数 inorder() を定義します(引
-
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 までの階乗の値を表に整理