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

C++で配列をK回連結した後に作成される配列の最大サブ配列合計を求める方法

このチュートリアルでは、配列を繰り返し連結して作成される配列における最大サブ配列合計(Maximum Subarray Sum)を求めるC++プログラムについて解説します。

具体的には、1つの配列と整数Kが与えられ、元の配列をK回繰り返して連結した配列の中から、要素の合計が最大となる連続する部分配列(サブ配列)を見つけることが課題となります。

アルゴリズムのポイント

この問題は、有名なカダネのアルゴリズム(Kadane's Algorithm)を応用することで効率的に解けます。

  • ループは n * k 回実行します(連結後の配列全体を走査)。
  • a[i % n] のように剰余演算を使うことで、実際に大きな配列を作成せずとも、元の配列を循環的に参照できます。
  • max_ending_here は現在注目している部分配列の合計を保持し、負になった時点で0にリセットします。
  • max_so_far はこれまでに見つかった最大合計を記録していきます。

サンプルコード

#include<bits/stdc++.h>
using namespace std;
// 最大サブ配列の合計を返す関数
int maxSubArraySumRepeated(int a[], int n, int k) {
    int max_so_far = INT_MIN, max_ending_here = 0;
    for (int i = 0; i < n*k; i++) {
        max_ending_here = max_ending_here + a[i%n];
        if (max_so_far < max_ending_here)
            max_so_far = max_ending_here;
        if (max_ending_here < 0) max_ending_here = 0;
    }
    return max_so_far;
}
int main() {
    int a[] = {10, 20, -30, -1};
    int n = sizeof(a)/sizeof(a[0]);
    int k = 3;
    cout << "Maximum contiguous sum is "
        << maxSubArraySumRepeated(a, n, k);
    return 0;
}

実行結果

Maximum contiguous sum is 30

上記の例では、配列 {10, 20, -30, -1} を3回連結すると {10, 20, -30, -1, 10, 20, -30, -1, 10, 20, -30, -1} となります。この中で合計が最大となる連続部分配列は {10, 20} であり、その合計 30 が出力されます。

このように、剰余演算による循環参照を利用すれば、連結後の巨大な配列を実際にメモリ上に構築することなく、時間計算量 O(n×k) で最大サブ配列合計を求めることができます。

  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++で繰り返し減算により全要素を等しくした後の最大配列合計を求める方法

    n個の要素からなる配列が与えられたとします。このとき、すべての要素を同じ値にした状態での、要素の合計の最大値を求めることを考えます。ただし、許されている操作は「任意の2つの要素を選び、大きい方の値を2つの差(絶対値)で置き換える」というものだけです。例として、配列が [9, 12, 3, 6] の場合を考えてみましょう。この場合の出力は 12 になります。手順の例A[1] を A[1] − A[3] = 12 − 6 = 6 に置き換えます。→ 配列は [9, 6, 3, 6]A[3] を A[3] − A[2] = 6 − 3 = 3 に置き換えます。→ 配列は [9, 6, 3, 3]A[