C++で配列の最大トリプレット和を求める方法【初心者向け解説】
この記事では、与えられた配列の中から3つの要素を選んだときの合計(トリプレット和)が最大になる組み合わせを見つけるプログラムをC++で作成します。
問題の概要
配列が与えられたとき、その中から3つの要素を選び、その合計が最大となる組み合わせを求めるのが課題です。
具体例で理解しよう
入力: array = {4, 6, 1, 2}
出力: 12
解説:
すべてのトリプレットの組み合わせ: (4, 6, 1) = 4 + 6 + 1 = 11 (4, 6, 2) = 4 + 6 + 2 = 12 (4, 1, 2) = 4 + 1 + 2 = 7 (6, 1, 2) = 6 + 1 + 2 = 9 最大トリプレット和は 12
方法1:全探索(ブルートフォース)によるアプローチ
最もシンプルな方法は、上記の例のようにすべてのトリプレットの組み合わせについて合計を計算し、その中から最大値を見つけることです。
具体的には、3重ループを回して考えられるすべてのトリプレット和を求め、現在の最大値(maxSum)よりも大きければ更新していきます。
ただし、この方法の計算量は O(n³) となるため、配列の要素数が大きくなると処理時間が急激に増加し、実用的ではありません。
サンプルコード
#include <iostream>
using namespace std;
int maxSum(int arr[], int n){
int maxSum = 0;
int i, j, k;
// すべてのトリプレットの組み合わせを調べる
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
for (k = j + 1; k < n; k++)
if (maxSum < arr[i] + arr[j] + arr[k])
maxSum = arr[i] + arr[j] + arr[k];
return maxSum;
}
int main(){
int arr[] = { 3, 5, 7, 1, 9, 0 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << "配列の最大トリプレット和は " << maxSum(arr, n);
return 0;
}
実行結果
配列の最大トリプレット和は 21
方法2:ソートを活用した効率的なアプローチ
より効率的な方法は、まず配列を昇順にソートし、末尾(最大値側)の3つの要素の合計を返すというものです。
ソート後の配列では最も大きい3つの要素が末尾に集まるため、それらの合計が必然的に最大トリプレット和となります。計算量は O(n log n) に抑えられ、全探索と比べて大幅に高速です。
サンプルコード
#include <bits/stdc++.h>
using namespace std;
int maxSum(int arr[], int n) {
// 配列を昇順にソート
sort(arr, arr + n);
// 最大の3要素の合計を返す
return arr[n - 1] + arr[n - 2] + arr[n - 3];
}
int main() {
int arr[] = { 3, 5, 9, 1, 2, 8, 7 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << "配列の最大トリプレット和は " << maxSum(arr, n);
return 0;
}
実行結果
配列の最大トリプレット和は 24
まとめ
| アプローチ | 計算量 | 特徴 |
|---|---|---|
| 全探索(3重ループ) | O(n³) | シンプルだが大規模データには不向き |
| ソート+上位3要素 | O(n log n) | 高速かつ実装も簡潔で推奨 |
実務や競技プログラミングでは、ソートを利用した方法2のアプローチを採用するのがベストです。なお、負の数を含む配列にも対応させたい場合は、初期値 maxSum を INT_MIN など適切な最小値で初期化することをおすすめします。
-
C++で配列を最大K個に分割して平均の合計を最大化する方法
問題概要 数値の配列 A が与えられます。この配列を最大 K 個の隣接する(空でない)グループに分割し、スコアを「各グループの平均値の合計」と定義します。このとき、達成できる最大スコアを求めるのが本問題です。 入力例 入力配列が {9, 2, 5, 3, 10} の場合、たとえば次のように分割できます。 {9} {2, 5, 3} {10} このときの平均の合計は次のとおりです。 9 + (2 + 5 + 3) / 3 + 10 = 22.33 アルゴリズム(メモ化再帰) この問題は、メモ化(記憶化)再帰を使うことで効率よく解くことができます。 memo[i][k]:A[i]〜A[n-1]
-
C++の配列パズル:減算演算子を使わずに「自分以外の要素の合計」を求める方法
今回は、配列に関する興味深い問題を紹介します。n個の要素を持つ配列が与えられ、それをもとに同じくn個の要素を持つ別の配列を作成します。ただし、新しい配列のi番目には、元の配列のi番目の要素を除いたすべての要素の合計を格納します。さらに重要な制約として、減算演算子(-)を使用してはいけないという条件が課されています。 問題のポイント もし減算が使えるのであれば、話は簡単です。まず全要素の合計を求めておき、そこからi番目の要素を引いた値を新しい配列のi番目に格納すればよいだけです。しかし、この問題では減算が禁止されているため、別のアプローチが必要になります。 そこで、各位置i(0〜n-1)について