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

C++でn個の配列から昇順要素を選んで最大合計を求める方法

このチュートリアルでは、n個の配列から「昇順」という条件を満たすように要素を1つずつ選び、その合計を最大化するプログラムについて解説します。

ここでは、サイズMの配列がN個与えられます。各配列から1つずつ要素を選び、「前の配列から選んだ要素よりも、次の配列から選ぶ要素の方が大きい」という条件を満たしながら、合計の最大値を求めることが課題です。

アルゴリズムの考え方

この問題は、貪欲法(グリーディ法)を用いることで効率的に解くことができます。手順は以下の通りです。

  1. まず、すべての配列をそれぞれ昇順にソートします。
  2. 最後の配列の最大要素(末尾の要素)を出発点とし、これを合計の初期値とします。
  3. 後ろの配列から前の配列へ向かって処理を進めます。各配列については末尾側から探索し、「直前に選んだ要素より小さい要素」の中で最も大きいものを選びます。
  4. ある配列で条件を満たす要素が1つも存在しない場合は、有効な選び方が存在しないため0を返します。

後ろから処理を進めることで、各ステップで「条件を満たす中でできるだけ大きな値」を選択でき、結果的に全体の合計が最大化されます。

実装例

#include <bits/stdc++.h>
#define M 4
using namespace std;
//1つの要素を選んで最大合計を計算する
int maximumSum(int a[][M], int n) {
    for (int i = 0; i < n; i++)
        sort(a[i], a[i] + M);
    int sum = a[n - 1][M - 1];
    int prev = a[n - 1][M - 1];
    int i, j;
    for (i = n - 2; i >= 0; i--) {
        for (j = M - 1; j >= 0; j--) {
            if (a[i][j] < prev) {
                prev = a[i][j];
                sum += prev;
                break;
            }
        }
        if (j == -1)
            return 0;
    }
    return sum;
}
int main() {
    int arr[][M] = {
        {1, 7, 3, 4},
        {4, 2, 5, 1},
        {9, 5, 1, 8}
    };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << maximumSum(arr, n);
return 0;
}

出力

18

動作の解説

上記の入力例では、各配列をソートすると {1, 3, 4, 7}、{1, 2, 4, 5}、{1, 5, 8, 9} となります。

  • 最後の配列から最大値「9」を選択します。
  • 2番目の配列から「9より小さい最大値」である「5」を選択します。
  • 1番目の配列から「5より小さい最大値」である「4」を選択します。

したがって、合計は 9 + 5 + 4 = 18 となります。

計算量

ソートに各配列あたりO(M log M)かかるため、全体の時間計算量はO(N × M log M)です。その後の要素選択はO(N × M)で完了します。空間計算量はO(1)で、入力配列をそのまま利用するため追加メモリは不要です。

  1. C++で厳密に増加する部分配列の最大和を求めるアルゴリズム

    問題の概要n 個の整数からなる配列が与えられたとき、その中に存在する「厳密に増加する(strictly increasing)部分配列」の中で、要素の合計が最大となるものを求めます。例として、次のような配列を考えてみましょう。[1, 2, 3, 2, 5, 1, 7]この配列には、厳密に増加している部分配列が3つ存在します。{1, 2, 3}{2, 5}{1, 7}それぞれの合計は 6、7、8 となり、この中で最大となるのは {1, 7} の合計 8 です。解き方の考え方この問題は、現在の部分配列の合計(current_sum)とこれまでの最大合計(max_sum)を追跡しながら配列を一度だけ

  2. C++で配列内の重複しない(一意な)要素の合計を求める方法

    問題の概要いくつかの要素を含む配列 A があるとします。この配列から、すべての一意な(重複しない)要素の合計を求める必要があります。例えば、配列が A = [5, 12, 63, 5, 33, 47, 12, 63] の場合を考えてみましょう。このとき、一意な要素は「5, 12, 63, 33, 47」であり、その合計は 160 になります。重複している要素は、一度合計に加算された後は単純に無視されます。解決のアプローチこの問題は、C++の unordered_set(ハッシュセット)を使うことで効率的に解決できます。基本的な考え方は以下のとおりです。forループを1回だけ実行して配列を走査す