C++で最大の幾何平均を持つサブセットを検索する方法
問題の概要
ここでは、複数の要素を含む配列 A が与えられ、その中から幾何平均が最大となるサブセットを見つけることが課題となります。
例として、A = [1, 5, 7, 2, 0] という配列を考えてみましょう。この場合、最大の幾何平均を持つサブセットは [5, 7] になります。
解法のアプローチ
この問題には便利な性質があります。すべての要素が正の数である場合、配列内で最も大きい2つの要素を選べば、それらの組み合わせが必ず最大の幾何平均を持つことが数学的に保証されています。これは、幾何平均は要素の積の n 乗根であり、正の数同士では要素数が増えるほど(1より大きい値のみなら別ですが)平均が引き下げられる可能性があるためです。
したがって、幾何平均を実際に計算する必要はなく、以下の手順で解くことができます。
- 配列を1回走査して、最大値と2番目に大きい値を求める
- その2つの値をサブセットとして出力する
この方法なら、計算量はわずか O(n)、追加のメモリも不要(O(1))で非常に効率的です。
C++での実装例
#include <iostream>
using namespace std;
void largestGeoMeanSubset(int arr[], int n) {
// 要素が2つ未満の場合はサブセットを作れない
if (n < 2) {
cout << "Very few number of elements";
return;
}
int max = INT_MIN, second_max = INT_MIN;
// 1回の走査で最大値と2番目に大きい値を求める
for (int i = 0; i < n; i++) {
if (arr[i] > max) {
second_max = max;
max = arr[i];
} else if (arr[i] > second_max) {
second_max = arr[i];
}
}
cout << second_max << ", " << max;
}
int main() {
int arr[] = {1, 5, 7, 2, 0};
int n = sizeof(arr) / sizeof(arr[0]);
largestGeoMeanSubset(arr, n);
}出力結果
5, 7
コードの解説
このプログラムの動作を順に見ていきましょう。
- 要素数のチェック: 要素が2つ未満の場合、サブセットを構成できないためメッセージを表示して終了します。
- 変数の初期化: 最大値を格納する
maxと、2番目に大きい値を格納するsecond_maxをINT_MINで初期化します。 - 1回の走査: 各要素について、現在の最大値より大きければ
maxを更新し、元のmaxの値をsecond_maxへ繰り下げます。最大値より小さくてもsecond_maxより大きい場合はsecond_maxを更新します。 - 結果の出力: 見つかった2つの値を出力します。サンプル配列 {1, 5, 7, 2, 0} では、最大値 7 と2番目に大きい値 5 が検出され、「5, 7」が出力されます。
注意点
この手法はすべての要素が正の数(または非負)である場合に有効です。負の数やゼロが含まれる配列では、幾何平均の挙動が変わるため、別途ケース分けが必要になる点に留意してください。
-
C++で重複要素を含むソート済み配列から不動点を効率的に検索する方法
本記事では、与えられた配列の中から「不動点(Fixed Point)」を見つける方法を解説します。不動点とは、配列の要素の値がそのインデックスと一致している箇所のことです。例えば、arr[2] = 2 のような場合、インデックス2が不動点となります。このプログラムは、不動点が存在すればその値を返し、存在しない場合は -1 を返します。なお、配列には負の数も含めることができ、要素は昇順にソートされているものとします。さらに、この問題では重複した要素が存在することを許容している点がポイントです。アルゴリズムの考え方:修正版二分探索この問題は、二分探索を使えば O(log n) の時間計算量で解くこ
-
C++で配列内の最大GCDを持つペアを検索する方法
問題の概要正の整数で構成される配列が与えられたとき、その中からGCD(最大公約数)が最大となる整数のペアを見つけるのがこの記事のテーマです。例として、配列 A = {1, 2, 3, 4, 5} を考えてみましょう。この場合の出力は 2 になります。ペア (2, 4) のGCDが 2 であり、それ以外のどのペアのGCDも 2 未満にしかならないためです。解法のアプローチこの問題を効率的に解くには、各約数の出現回数を記録するカウント配列を活用します。全体の流れは次の通りです。配列内の各要素について約数をすべて列挙し、カウント配列に記録します。1つの要素の約数列挙には O(√arr[i]) の時間