C++で配列の最大積サブセットを求めるアルゴリズムと実装方法
このチュートリアルでは、配列の中から部分集合を選び、その積が最大になる値を求めるプログラムについて解説します。
ここでは、正の値と負の値が混在する配列が与えられます。私たちのタスクは、この配列の部分集合の中で積が最大となるものを見つけることです。
アルゴリズムの考え方
最大積を求めるための基本的な戦略は以下の通りです。
- 0は乗算に含めない:0を掛けると積が0になってしまうため、計算から除外します。
- 負の数の扱い:負の数が偶数個ある場合はすべて掛けて問題ありません。奇数個の場合は、絶対値が最も小さい(0に最も近い)負の数を除外することで、積を最大化できます。
- 全要素が0の場合:配列のすべての要素が0であれば、答えは0になります。
- 負の数が1つだけで残りが0の場合:正の積を作れないため、答えは0になります。
サンプルコード
#include <bits/stdc++.h>
using namespace std;
int maxProductSubset(int a[], int n) {
// 要素が1つだけなら、その値が答え
if (n == 1)
return a[0];
int max_neg = INT_MIN; // 絶対値が最小の負の数
int count_neg = 0, count_zero = 0;
int prod = 1;
for (int i = 0; i < n; i++) {
// 0を掛けても意味がないのでスキップ
if (a[i] == 0) {
count_zero++;
continue;
}
if (a[i] < 0) {
count_neg++;
max_neg = max(max_neg, a[i]);
}
prod = prod * a[i];
}
// すべての要素が0の場合
if (count_zero == n)
return 0;
// 負の数が奇数個の場合
if (count_neg & 1) {
// 負の数が1つだけで、残りがすべて0の場合
if (count_neg == 1 &&
count_zero > 0 &&
count_zero + count_neg == n)
return 0;
// 絶対値が最小の負の数を除外する
prod = prod / max_neg;
}
return prod;
}
int main() {
int a[] = { -1, -1, -2, 4, 3 };
int n = sizeof(a) / sizeof(a[0]);
cout << maxProductSubset(a, n);
return 0;
}
出力
24
処理の流れの解説
上記の例では、配列 {-1, -1, -2, 4, 3} に対して処理を行っています。まず0以外の全要素の積を計算すると (-1) × (-1) × (-2) × 4 × 3 = -24 となります。負の数は3つ(奇数)なので、絶対値が最も小さい -1 を除外します。結果として -24 / (-1) = 24 が最大積として返されます。
このアルゴリズムは配列を一度走査するだけなので、時間計算量は O(n)、補助的な記憶領域は O(1) で済み、非常に効率的です。
-
【C++】配列内のすべての素数の積を求める方法
整数型配列 arr[] が与えられたとき、その配列に含まれるすべての素数を見つけ出し、それらの積を計算するのが本記事のテーマです。素数とは、1とその数自身でしか割り切れない正の整数のことです。たとえば、2、3、5、7、11などが素数に該当します。それでは、次の配列を例に解を求めてみましょう。入力: arr[] = { 11, 20, 31, 4, 5, 6, 70 }出力: 1705説明: 配列内の素数は 11、31、5 の3つであり、その積は 11 × 31 × 5 = 1705 となります。入力: arr[] = { 1, 2, 3, 4, 5, 6, 7 }出力: 210説明: 配列内の
-
C++でSTLを使って配列の積を求める方法
C++では、STL(標準テンプレートライブラリ)のaccumulate関数を利用することで、配列内のすべての要素の積を簡潔に求めることができます。ここでは、その具体的な実装例を紹介します。 アルゴリズム 開始 配列の各要素の値を初期化する。 ユーザー定義関数 accumulate を呼び出し、配列全体の積を取得する。 計算結果を出力する。 終了 サンプルコード #include <iostream> #include <numeric> using namespace std; int ProductOfArray(int p[], int n)