Kadenceov algoritam: Susjedni podniz s najvećim zbrojem

⚡ Pametni sažetak

Kadaneov algoritam pronalazi najveću sumu susjednih podnizova u linearnom vremenu pomoću trackraljujte tekući maksimum umjesto skeniranja svakog mogućeg podniza. Ovaj klasični trik dinamičkog programiranja pokreće probleme s dionicama, financijama i signalima.

  • 🎯 Definicija problema: Susjedni podniz je niz uzastopnih elemenata; cilj je podniz s najvećim aritmetičkim zbrojem unutar miješanog pozitivnog i negativnog niza.
  • ???? Gruba sila: Dvije ugniježđene petlje procjenjuju svaki početni i završni indeks u vremenu O(N²) i ispisuju pobjednički prozor koristeći početne i završne markere.
  • Kadaneov uvid: Resetiraj tekući zbroj kad god trenutni element pobijedi akumulator, zadržiping samo najbolji prefiks koji je još mogao prerasti u odgovor.
  • 🧭 Obrađeni primjer: Kratak pregled niza s negativnim vrijednostima pokazuje kako se max_sum i current_sum korak po korak razvijaju sve dok se ne postigne pravi maksimum.
  • 💻 Jezična pokrivenost: Oboje C++ i Python Implementacije jednostavnog pristupa i Kadaneovog algoritma pokazuju prijelaz s vremena O(N²) na O(N).
  • 📊 Složenost: Kadaneov algoritam se izvršava u O(N) vremenu s O(1) dodatnog prostora, dramatično nadmašujući osnovni algoritam grube sile na velikim ulaznim nizovima.

Kadaneov algoritam Najveći zbroj susjednog podniza

Koji je najveći sum susjednog podniza?

Podniz je kontinuirani dio niza. To može biti jedan element niza ili neki dio niza. Susjedni podniz najvećeg zbroja znači podniz koji ima najveću vrijednost zbroja.

Na primjer, uzmite niz {-10, 5, 1, 6, -9, 2, -7, 3, -5}. Njegovi podnizovi mogu biti {-10, 5, 1, 6}, {5, 1, 6} ili {2, -7, 3, -5} i tako dalje. Međutim, {5, 1, 6, 3} ne može biti podniz jer elementi nisu u susjednom nizu.

Najveća suma kontinuiranog podniza

Ako primijetite, među svim podnizovima, istaknuti podniz {5, 1, 6} ima maksimalnu vrijednost zbrajanja:

Najveći sum susjednog podniza označen

Zbroj podniza {5, 1, 6} je 12, što je maksimalni zbroj svih mogućih podnizova gornjeg niza. Dakle, za ovaj niz, maksimalni zbroj susjednog podniza je {5, 1, 6}.

Jednostavan pristup rješavanju susjednog podniza s najvećim zbrojem

Jednostavan način rješavanja ovog problema je korištenje dvije petlje za pronalaženje svih podnizova, izračunavanje zbroja, a zatim pronalaženje njegove maksimalne vrijednosti.

Evo dijagrama toka za jednostavan pristup pronalaženju najvećeg zbroja susjednog podniza. Ovo je pristup grube sile, jer prolazimo kroz svaki mogući podniz.

Jednostavan pristup rješavanju najvećeg zbroja

Evo jednostavnih koraka za to.

Korak 1) inicijalizirati maks_zbroj s minimalnom cjelobrojnom vrijednošću i skupom krene i kraj na nulu.

Korak 2) Dopustite da vas i i j biti indeksi polja gdje j je veće ili jednako i; i označava početak podniza i j njegov kraj.

Korak 3) trenutni_zbroj sadrži tekući zbroj. Nakon svakog ažuriranja, provjerite je li trenutni_zbroj je veći od maks_zbroj.

Korak 4) If trenutni_zbroj je veći, zamijenite maks_zbroj s njom.

Korak 5) Kada j dođe do kraja niza, inkrement i i resetirati trenutni_zbroj na 0.

Korak 6) Ponavljajte dok i dođe do kraja niza. maks_zbroj tada sadrži najveću sumu podniza.

Nadimak Code za jednostavan pristup

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

C++ Implementacija jednostavnog pristupa

#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]));
}

Izlaz:

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

Python Implementacija jednostavnog pristupa

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)

Izlaz:

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

Kadaneov algoritam za pronalaženje najvećeg zbroja susjednog podniza

Kadaneov algoritam je metoda dinamičkog programiranja koja koristi jednu petlju umjesto dvije. Obrađuje nizove s miješanim pozitivnim i negativnim brojevima, sve dok je barem jedna vrijednost nenegativna.

Trebaju nam samo dvije varijable da bismo pronašli najveću sumu susjednog podniza. Evo dijagrama toka:

Kadaneov algoritam za pronalaženje najvećeg zbroja

Evo koraka za Kadaneov algoritam:

Korak 1) Stvorite dvije varijable, trenutni_zbroj i maks_zbroj.

trenutni_zbroj zadržava maksimalnu sumu koja završava na određenom indeksu polja, dok maks_zbroj pohranjuje najveću do sada opaženu vrijednost zbrajanja.

Korak 2) Dodaj svaki element niza u trenutni_zbrojZatim provjerite dva uvjeta u nastavku:

  • If trenutni_zbroj je manji od trenutnog elementa, tada trenutni_zbroj postaje trenutni element.
  • If maks_zbroj je manje od trenutni_zbroj, A zatim maks_zbroj postaje trenutni_zbroj.

Korak 3) Nakon ponavljanja prethodnog koraka za cijeli niz, maks_zbroj sadrži najveću sumu susjednog podniza.

Primjer Kadaneovog algoritma

Demonstriramo Kadaneov algoritam na malom nizu i prolazimo kroz svaki korak pronalaženja najveće sume susjednog podniza.

Pretpostavimo da je zadani niz ovakav:

Primjer Kadaneovog algoritma

Evo koraka Kadaneovog algoritma:

Korak 1) Stvorite dvije varijable, trenutni_zbroj i maks_zbrojDodijeli INT_MIN za maks_zbroj i nula do trenutni_zbrojOvdje INT_MIN predstavlja minimalnu cjelobrojnu vrijednost.

Korak 2) Na indeksu 0, vrijednost je 4. Dakle, trenutni_zbroj = 0 + 4 = 4. Budući da trenutni_zbroj je veći od maks_zbroj, maks_zbroj postaje 4.

Primjer Kadaneovog algoritma, korak 2

Korak 3) Na indeksu 1, vrijednost je -2. Dakle, trenutni_zbroj = 4 + (-2) = 2.

Ovaj put trenutni_zbroj je manje od maks_zbrojKao rezultat toga, vrijednost maks_zbroj nije ažuriran.

Primjer Kadaneovog algoritma, korak 3

Korak 4) Sljedeća vrijednost je 1. Dodavanjem u trenutni_zbroj daje 3. Budući da maks_zbroj (4) je još uvijek veći od trenutni_zbroj, maks_zbroj nije ažuriran.

Primjer Kadaneovog algoritma, korak 4

Korak 5) Na indeksu 3, vrijednost je 3. Povećanje trenutni_zbroj za 3 daje trenutni_zbroj = 6.

Primjer Kadaneovog algoritma, korak 5

U ovom slučaju, maks_zbroj je manji od trenutni_zbroj, Tako da maks_zbroj ažurira se s vrijednošću od trenutni_zbroj.

Korak 6) Za posljednji element niza imamo -1. Dodavanjem u trenutni_zbroj daje 5, što je manje od maks_zbroj, Tako, maks_zbroj ostaje 6.

Primjer Kadaneovog algoritma, korak 6

Kako smo došli do kraja niza, algoritam ovdje završava. Sada, maks_zbroj sadrži maksimalnu sumu, koja je 6. Podniz je {4, -2, 1, 3}.

Nadimak Code za Kadaneov algoritam

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++ Implementacija Kadaneovog algoritma

#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]));
}

Izlaz:

largest sum is 12

Python Implementacija Kadaneovog algoritma

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])

Izlaz:

largest sum is 12

Analiza složenosti za najveći sumski kontinuirani podniz

Jednostavan pristup koristi dvije petlje za izračunavanje svake moguće sume podniza i lociranje najveće. To je pristup grube sile; svaka petlja se izvršava do kraja poredak, dajući O(N²) vrijeme.

Kadaneov algoritam koristi samo jednu petlju, što daje O(N) vremena i O(1) dodatnog prostora. Na nizu od 100 elemenata jednostavan pristup izvodi 100 × 100 = 10 000 operacija, dok Kadaneov izvodi samo 100 - dramatično ubrzanje za velike ulaze.

Pitanja i odgovori

Kadaneov algoritam podupire inženjering značajki umjetne inteligencije za podatke vremenskih serija, otkrivanje prozora anomalija i nagrađivanje.ping u učenju s potkrepljenjem, pomoćping Modeli uočavaju najjači interval pozitivne sume u signalima s šumom.

Da. GitHub Copilot i GPT pouzdano ispisuju Kadaneov algoritam u Python, C++i Java, uključujući varijante koje vraćaju početni i završni indeks pobjedničkog podniza.

Kadaneov algoritam se izvršava u O(N) vremenu i O(1) pomoćnom prostoru jer obavlja jedan prolaz trackralj samo tekući iznos i najbolja do sada vrijednost.

Inicijalizirajte max_sum na prvi element ili na minus beskonačnost umjesto na nulu. Algoritam zatim vraća najmanje negativan element, što je točan odgovor.

Uobičajene upotrebe su prozori profita od kupnje i prodaje dionica, zbrojevi rubova slika, intervali bodovanja genomike i analiza financijskog rizika gdje je najbolji susjedni prozor povrata najvažniji.

Tracka privremeni početni indeks kad god se current_sum resetira na trenutni element. Kada se max_sum ažurira, uhvati početni i završni indeks tako da se podniz odgovora može izrezati na kraju.

Metoda "podijeli pa vladaj" rješava maksimalni podniz u O(N log N) kombiniranjem lijeve, desne i ukrštanja zbrojeva. Kadaneov algoritam je brži na O(N) i lakši za kodiranje.

Da. Kadaneov je kanonski primjer dinamičkog programiranja s O(1) stanjem, gdje svaki novi maksimum koji završava na indeksu i ovisi o maksimumu koji završava na indeksu i minus jedan plus trenutni element.

Sažmite ovu objavu uz: