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

KadaneのアルゴリズムでJavaScriptの最大部分配列和を線形時間で求める方法


問題

正と負の整数が混在する配列 arr を唯一の引数として受け取るJavaScript関数を作成します。

この関数は、配列内の任意の部分配列(連続する要素の集まり)の合計として考えられる最大値を、線形時間 O(n) で返す必要があります。

Kadaneのアルゴリズムの考え方

任意のインデックス i における「局所最大値(local_maximum)」とは、arr[i] 単独の値と、arr[i] + インデックス i-1 の局所最大値 のうち大きい方を指します。

この考え方を配列の先頭から順に適用していけば、配列全体をたった一度の走査で処理するだけで、最大部分配列和を効率よく求めることができます。

入力例と出力例

例えば、関数に次のような配列を渡したとします。

入力

const arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4];

出力

const output = 6;

出力の解説

合計が最大となる部分配列は以下の通りです。

[4, -1, 2, 1]

4 + (-1) + 2 + 1 = 6 となり、この配列で達成可能な最大の部分配列和は6になります。途中に負の要素が含まれていても、それを含めた方が合計が大きくなるケースでは、あえて含めるのが最適解となります。

実装コード

以下が実際のコードです。

const arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4];
const maxSequence = (arr = []) => {
    let currentSum = 0;
    let maxSum = 0;

    for (let elem of arr) {
        const nextSum = currentSum + elem;
        maxSum = Math.max(maxSum, nextSum);
        currentSum = Math.max(nextSum, 0);
    }

    return maxSum;
};
console.log(maxSequence(arr));

出力結果

6

コードのポイント

この実装では、変数 currentSum が「現在位置までの累積和」を表し、負になった時点で 0 にリセットされます。これは、それまでの累積和が以降の部分配列にとって不利にしか働かないためです。一方、maxSum はこれまでに登場した最大の合計を常に記録しており、ループ終了後に答えとして返されます。計算量は O(n)、追加メモリも O(1) と非常に効率的です。

  1. C++のプレフィックス和(累積和)を活用してO(n)で最大部分配列和を求める方法

    問題概要 正の整数と負の整数が混在する配列が与えられたとき、その配列の中で合計値が最大となる部分配列(連続した要素の並び)の合計を求める問題です。 例 入力配列が {-12, -5, 4, -1, -7, 1, 8, -3} の場合、合計が最大になる部分配列は {1, 8} となるため、出力は 9 になります。 アルゴリズム この問題は、プレフィックス和(累積和)を利用することで O(n) の時間計算量で効率的に解くことができます。考え方の核心は、「ある位置 i で終わる部分配列の合計の最大値」は「prefix_sum[i] から、それ以前に現れた最小の累積和を引いた値」で表せるという点です

  2. Kadaneのアルゴリズムで最大部分配列問題を解くPythonプログラム

    Kadane(カデイン)のアルゴリズムを使って最大部分配列(Maximum Subarray)を求めたい場合、部分配列の最大値を見つけるための専用メソッドを定義します。そして、イテレーション(繰り返し処理)を通じて最大部分配列を追跡していきます。以下に具体的な実装例を示します。サンプルコードdef find_max_sub_array(my_list, beg, end): max_end_at_i = max_seen_till_now = my_list[beg] max_left_at_i = max_left_till_now = beg max_right_t