Kadence のアルゴリズム: 最大合計連続サブ配列

⚡ スマートサマリー

カダネのアルゴリズムは、線形時間で最大合計連続部分配列を見つけます。 trac考えられるすべての部分配列を走査する代わりに、最大値を動的に求める。この古典的な動的計画法の手法は、株式、金融、シグナル問題に活用されている。

  • 🎯 問題の定義: 連続部分配列とは、連続する要素の列のことです。目標は、正負の要素が混在する配列の中で、算術和が最も大きい部分配列を見つけることです。
  • 🐢 ブルートフォース: 2つのネストされたループは、O(N²)の時間ですべての開始インデックスと終了インデックスを評価し、開始マーカーと終了マーカーを使用して勝者ウィンドウを出力します。
  • カダンの洞察: 現在の要素がアキュムレータを上回るたびに累積合計をリセットします。ping 答えに発展する可能性のある、最良の接頭辞のみ。
  • 🧭 実例: 負の数を含む配列を簡単に見ていくと、max_sumとcurrent_sumが真の最大値が捉えられるまでどのように段階的に変化していくかがわかります。
  • 💻 言語範囲: 両方 C++ (NAIST) と Python 単純なアプローチとカダネのアルゴリズムの実装は、O(N²)からO(N)の時間への移行を示しています。
  • 📊 複雑: カダネのアルゴリズムはO(N)の時間でO(1)の追加メモリで実行され、大規模な入力配列に対して総当たり方式のベースラインを大幅に上回る性能を発揮します。

カダネのアルゴリズム:最大和連続部分配列

最大合計連続部分配列とは何ですか?

サブ配列は配列の連続した部分です。 配列の単一要素または配列の一部を指定できます。 最大和連続部分配列とは、最大和値を持つ部分配列を意味します。

例えば、配列 {-10, 5, 1, 6, -9, 2, -7, 3, -5} を考えてみましょう。この配列の部分配列は、{-10, 5, 1, 6}、{5, 1, 6}、{2, -7, 3, -5} などになります。しかし、{5, 1, 6, 3} は要素が連続していないため、部分配列にはなり得ません。

最大合計連続サブアレイ

よく見ると、すべての部分配列の中で、強調表示されている部分配列 {5, 1, 6} の合計値が最大であることがわかります。

最大合計連続部分配列が強調表示されています

部分配列 {5, 1, 6} の合計は 12 であり、これは上記の配列のすべての可能な部分配列の中で最大の合計値です。したがって、この配列の場合、連続する部分配列の中で最大の合計値を持つのは {5, 1, 6} です。

連続部分配列の最大和を求めるためのシンプルなアプローチ

この問題を解決する簡単な方法は、XNUMX つのループを使用してすべての部分配列を見つけ、合計を計算し、その最大値を見つけることです。

以下は、連続する部分配列の合計が最大となる部分配列を見つけるための単純な方法を示すフローチャートです。これは、考えられるすべての部分配列を順に調べていく総当たり方式です。

最大額を解決するためのシンプルなアプローチ

これを行うための簡単な手順を次に示します。

ステップ1) 初期化します 最大合計 最小の整数値で設定し、 始まる (NAIST) と end ゼロに。

ステップ2) しましょう i (NAIST) と j 配列インデックスは j より大きいか等しい i; i サブアレイの開始を示し、 j その終わり。

ステップ3) 現在の合計 累積合計を保持します。更新ごとに、 現在の合計 より大きい 最大合計.

ステップ4) If 現在の合計 より大きい場合は、 最大合計 それと。

ステップ5)    j 配列の末尾に達したら、インクリメントする i リセットします 現在の合計 0へ。

ステップ6) まで繰り返す i 配列の末尾に到達します。 最大合計 そして、最大のサブアレイ合計値を保持します。

ニックネーム Code シンプルなアプローチ

function maximumSubarraySum():
    input: array
    for all possible subArray from array:
        calculate sum of each subarray
        store the maximum subArray
    return the maximum sum

C++ シンプルなアプローチの実装

#include <stdio.h>
#include <iostream>
using namespace std;
void maximumSubarraySum(int array[], int n) {
    int max_sum = -1e9;
    int begin = 0;
    int end = 0;
    for (int i = 0; i < n; i++) {
        int current_sum = 0;
        for (int j = i; j < n; j++) {
            current_sum += array[j];
            if (max_sum < current_sum) {
                max_sum = current_sum;
                begin = i;
                end = j;
            }
        }
    }
    cout << "largest sum is " << max_sum << endl;
    cout << "largest sum contiguous subarray: ";
    for (int i = begin; i <= end; i++) {
        cout << array[i] << "\t";
    }
}
int main() {
    int array[] = {-10, 5, 1, 6, -9, 2, -7, 3, -5};
    maximumSubarraySum(array, sizeof(array) / sizeof(array[0]));
}

出力:

largest sum is 12
largest sum contiguous subarray: 5      1       6

Python シンプルなアプローチの実装

def maximumSubarraySum(numbers):
    max_sum, begin, end = -1e9, 0, 0
    for i in range(len(numbers)):
        current_sum = 0
        for j in range(i, len(numbers)):
            current_sum += numbers[j]
            if max_sum < current_sum:
                max_sum = current_sum
                begin, end = i, j
    print("largest sum is ", max_sum)
    print("largest sum contiguous subarray: ", end='')
    for i in range(begin, end + 1):
        print(numbers[i], end='\t')

numbers = [-10, 5, 1, 6, -9, 2, -7, 3, -5]
maximumSubarraySum(numbers)

出力:

largest sum is 12
largest sum contiguous subarray: 5      1       6

カダネのアルゴリズムによる最大合計連続部分配列の探索

カダネのアルゴリズムは、2つのループではなく1つのループを使用する動的計画法です。少なくとも1つの値が非負であれば、正の数と負の数が混在する配列も処理できます。

連続する部分配列の合計が最大となる値を見つけるには、2つの変数のみが必要です。フローチャートは以下のとおりです。

最大和を求めるカダネのアルゴリズム

Kadane のアルゴリズムの手順は次のとおりです。

ステップ1) 2 つの変数を作成します。 現在の合計 (NAIST) と 最大合計.

現在の合計 特定の配列インデックスで終了する最大合計値を保持し、 最大合計 これまでに観測された最大の合計値を格納します。

ステップ2) 各配列要素を 現在の合計次に、以下の2つの条件を確認してください。

  • If 現在の合計 現在の要素より小さい場合、 現在の合計 現在の要素になります。
  • If 最大合計 よりも少ない 現在の合計をタップし、その後、 最大合計 になる 現在の合計.

ステップ3) 前の手順を配列全体に対して繰り返した後、 最大合計 連続する部分配列の中で最大の和値を持つ。

Kadane のアルゴリズムの例

本稿では、小さな配列を用いてカダネのアルゴリズムを実証し、連続する部分配列の合計が最大となる部分配列を見つけるまでのすべてのステップを順を追って説明します。

与えられた配列が以下のようになっていると仮定しましょう。

Kadane のアルゴリズムの例

カダンのアルゴリズムの手順は以下のとおりです。

ステップ1) 2 つの変数を作成します。 現在の合計 (NAIST) と 最大合計INT_MIN を代入します 最大合計 ゼロから 現在の合計ここで、INT_MINは最小の整数値を表します。

ステップ2) インデックス 0 の値は 4 です。したがって、 現在の合計 = 0 + 4 = 4。 現在の合計 より大きい 最大合計, 最大合計 4 になります。

カダネのアルゴリズムの例 ステップ2

ステップ3) インデックス 1 の値は -2 です。したがって、 現在の合計 = 4 + (-2) = 2。

今回 現在の合計 よりも少ない 最大合計結果として、 最大合計 更新されません。

カダネのアルゴリズムの例 ステップ3

ステップ4) 次の値は 1 です。 現在の合計 3を与える。 最大合計 (4)は依然としてより大きい 現在の合計, 最大合計 更新されません。

カダネのアルゴリズムの例 ステップ4

ステップ5) インデックス3では、値は3です。 現在の合計 3で 現在の合計 = 6。

カダネのアルゴリズムの例 ステップ5

この場合、 最大合計 より小さい 現在の合計ので、 最大合計 の値で更新されます 現在の合計.

ステップ6) 配列の最後の要素は -1 です。 現在の合計 5 を与えるが、これは 最大合計。 そう、 最大合計 残り6。

カダネのアルゴリズムの例 ステップ6

配列の末尾に到達したので、アルゴリズムはここで終了します。 最大合計 最大合計値である6が含まれています。部分配列は{4, -2, 1, 3}です。

ニックネーム Code カダンのアルゴリズムについて

function KadaneAlgorithm():
    input: array
    maximum_sum, current_sum = 0
    for each element in array:
        add the element with current_sum
        if current_sum is greater than the maximum_sum
            then maximum_sum = current_sum
        if current_sum is less than the element
            then current_sum = element
    return the value of maximum_sum

C++ Kadaneのアルゴリズムの実装

#include <iostream>
using namespace std;
void kadane(int array[], int n) {
    int current_sum = 0;
    int max_sum = -1e9;
    // -1e9 means -1,000,000,000
    for (int i = 0; i < n; i++) {
        current_sum += array[i];
        if (max_sum < current_sum) {
            max_sum = current_sum;
        }
        if (current_sum < array[i]) {
            current_sum = array[i];
        }
    }
    cout << "largest sum is " << max_sum << endl;
}
int main() {
    int array[] = {-10, 5, 1, 6, -9, 2, -7, 3, -5};
    kadane(array, sizeof(array) / sizeof(array[0]));
}

出力:

largest sum is 12

Python Kadaneのアルゴリズムの実装

def kadane(numbers):
    current_sum = 0
    max_sum = -1e9
    for i in range(len(numbers)):
        current_sum += numbers[i]
        if max_sum < current_sum:
            max_sum = current_sum
        if current_sum < numbers[i]:
            current_sum = numbers[i]
    print("largest sum is ", max_sum)

kadane([-10, 5, 1, 6, -9, 2, -7, 3, -5])

出力:

largest sum is 12

最大和連続部分配列の複雑性分析

単純なアプローチでは、2 つのループを使用してすべての可能なサブ配列の合計を計算し、最大のものを見つけます。これは総当たりアプローチです。各ループは、 配列、与える O(N²) 時間。

カダネのアルゴリズムはループを1つしか使用しないため、処理時間はO(N)、追加メモリはO(1)で済みます。100個の要素を持つ配列の場合、単純な手法では100×100=10,000回の演算が必要ですが、カダネのアルゴリズムではわずか100回の演算で済みます。これは、入力サイズが大きい場合に劇的な高速化を実現します。

よくあるご質問

カダネのアルゴリズムは、時系列データ、異常ウィンドウ検出、報酬シェアリングのためのAI特徴量エンジニアリングの基盤となっている。ping 強化学習では、ping モデルは、ノイズの多い信号の中から最も強い正の合計区間を特定する。

はい。GitHub CopilotとGPTは、Kadaneのアルゴリズムを確実に出力します。 Python, C++, Javaこれには、勝者となる部分配列の開始インデックスと終了インデックスを返すバリアントも含まれます。

カダネのアルゴリズムは、1回のパスで済むため、O(N)の時間計算量とO(1)の補助空間で動作します。 tracキングは、進行中の合計と、これまでの最高値のみを示します。

max_sumをゼロではなく、最初の要素または負の無限大で初期化します。すると、アルゴリズムは最も負の値が小さい要素を返します。これが正解です。

一般的な用途としては、株式の売買利益期間、画像エッジの合計、ゲノムスコアリングの間隔、そして最適な連続リターン期間が最も重要となる金融リスク分析などが挙げられる。

Tracka は、current_sum が現在の要素にリセットされるたびに一時的に開始するインデックスです。max_sum が更新されたら、開始インデックスと終了インデックスを取得し、最後に結果のサブ配列をスライスできるようにします。

分割統治法は、左和、右和、交差和を組み合わせることで、最大部分配列をO(N log N)の時間で解決します。カダネのアルゴリズムはO(N)とより高速で、コーディングも容易です。

はい。カダネのものは、O(1)の状態を持つ典型的な動的計画法の例であり、インデックス i における各新しい最大終了値は、インデックス i から 1 を引いた値に現在の要素を加えた値に依存します。