Алгоритм Каденса: суміжний підмасив з найбільшою сумою

⚡ Розумний підсумок

Алгоритм Кадане знаходить найбільшу суму суміжних підмасивів за лінійний час за допомогою tracкороль ковзного максимуму замість сканування кожного можливого підмасиву. Цей класичний трюк динамічного програмування допомагає вирішувати проблеми з акціями, фінансами та сигналами.

  • 🎯 Визначення проблеми: Суміжний підмасив — це послідовність послідовних елементів; метою є підмасив з найбільшою арифметичною сумою всередині змішаного додатного та від'ємного масиву.
  • ???? Груба сила: Два вкладені цикли обчислюють кожен початковий та кінцевий індекс за час O(N²) та виводять вікно-переможець, використовуючи маркери початку та кінця.
  • Думка Кадане: Скидати поточну суму щоразу, коли поточний елемент перевищує значення акумулятора, зберігатиping лише найкращий префікс, який все ще міг би перетворитися на відповідь.
  • 🧭 Приклад роботи: Короткий огляд масиву з від'ємними числами показує, як max_sum та current_sum змінюються крок за кроком, доки не буде досягнутий справжній максимум.
  • 💻 Мовне покриття: обидві C++ та 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}.

Простий підхід до розв'язання найбільшої суми неперервного підмасиву

Простий спосіб розв’язати цю задачу — використати два цикли, щоб знайти всі підмасиви, обчислити суму, а потім знайти її максимальне значення.

Ось блок-схема простого підходу до знаходження найбільшої суми неперервних підмасивів. Це метод перебору, оскільки ми проходимо через усі можливі підмасиви.

Простий підхід до розв’язування найбільшої суми

Ось прості кроки для цього.

Крок 1) форматувати максимальна_сума з мінімальним цілочисельним значенням та набором починати та кінець до нуля.

Крок 2) Дозволяти i та 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

Алгоритм Кадане для знаходження найбільшої суми суміжних підмасивів

Алгоритм Кадане — це метод динамічного програмування, який використовує один цикл замість двох. Він обробляє масиви зі змішаними додатними та від'ємними числами, якщо хоча б одне значення є невід'ємним.

Нам потрібно лише дві змінні, щоб знайти найбільшу суму неперервного підмасиву. Ось блок-схема:

Алгоритм Кадане для знаходження найбільшої суми

Ось кроки для алгоритму Кадане:

Крок 1) Створіть дві змінні, поточна_сума та максимальна_сума.

поточна_сума зберігає максимальну суму, яка закінчується на певному індексі масиву, тоді як максимальна_сума зберігає найбільше значення суми, яке спостерігалося до цього часу.

Крок 2) Додати кожен елемент масиву до поточна_сумаПотім перевірте дві умови нижче:

  • If поточна_сума менше, ніж поточний елемент, тоді поточна_сума стає поточним елементом.
  • If максимальна_сума менше, ніж поточна_сума, То максимальна_сума стає поточна_сума.

Крок 3) Після повторення попереднього кроку для всього масиву, максимальна_сума містить найбільшу суму суміжного підмасиву.

Приклад алгоритму Кадане

Ми демонструємо алгоритм Кадане на невеликому масиві та розглянемо кожен крок знаходження найбільшої суми неперервного підмасиву.

Припустимо, що заданий масив має такий вигляд:

Приклад алгоритму Кадане

Ось кроки алгоритму Кадане:

Крок 1) Створіть дві змінні, поточна_сума та максимальна_сумаПризначте 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++ Реалізація алгоритму Кадане

#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 Реалізація алгоритму Кадане

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

Аналіз складності для суміжного підмасиву з найбільшою сумою

Простий підхід використовує два цикли для обчислення кожної можливої ​​суми підмасиву та знаходження найбільшої з них. Це підхід методом перебору; кожен цикл виконується до кінця масив, даючи O(N²) часу.

Алгоритм Кадане використовує лише один цикл, що дає O(N) часу та O(1) додаткового простору. На масиві зі 100 елементів простий підхід виконує 100 × 100 = 10 000 операцій, тоді як підхід Кадане виконує лише 100 — значне прискорення для великих вхідних даних.

Поширені запитання

Алгоритм Кадане лежить в основі розробки функцій штучного інтелекту для даних часових рядів, виявлення вікон аномалій та розподілу винагород.ping у навчанні з підкріпленням, helping Моделі виявляють найсильніший інтервал позитивної суми в зашумлених сигналах.

Так. GitHub Copilot та GPT надійно виводять алгоритм Кадане в Python, C++ та Java, включаючи варіанти, що повертають початковий та кінцевий індекси виграшного підмасиву.

Алгоритм Кадане виконується за час O(N) та у допоміжному просторі O(1), оскільки він виконує один прохід. tracкороль лише поточну суму та найкраще наразі значення.

Ініціалізуйте max_sum першим елементом або мінус нескінченністю замість нуля. Потім алгоритм повертає найменший від'ємний елемент, який є правильною відповіддю.

Зазвичай використовуються вікна прибутку від купівлі-продажу акцій, суми меж зображень, інтервали геномної оцінки та аналіз фінансових ризиків, де найкраще суміжне вікно прибутковості має найбільше значення.

Tracтимчасовий початковий індекс щоразу, коли current_sum скидається до поточного елемента. Коли max_sum оновлюється, фіксує початковий та кінцевий індекси, щоб підмасив відповідей можна було розділити в кінці.

Метод «розділяй і володарюй» розв'язує максимальний підмасив за O(N log N) шляхом комбінування лівих, правих та перехресних сум. Алгоритм Кадане швидший за O(N) і простіший у кодуванні.

Так. Приклад Кадане — це канонічний приклад динамічного програмування зі станом O(1), де кожен новий максимум, що закінчується в індексі i, залежить від максимуму, що закінчується в індексі i, мінус один плюс поточний елемент.

Підсумуйте цей пост за допомогою: