Kadenceov algoritam: Susjedni podniz s najvećim zbrojem

Koji je najveći zbroj kontinuiranog 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, niz je {-10, 5, 1, 6, -9, 2, -7, 3, -5}. Njegovi podnizovi mogu biti: {-10,5,1,6} ili {5,1,6} ili {2,7,3, -5} itd. Ali {5,1,6,3} ne može biti podniz jer ne održavaju nizove.

Najveća suma kontinuiranog podniza

Ako primijetite, među svim podnizovima, sljedeći označeni podnizovi (5,1,6) imaju najveću vrijednost zbroja:

Najveća suma kontinuiranog podniza

Zbroj podniza {5,1,6} = 11 je najveći zbroj u svim mogućim kombinacijama podniza gornjeg niza. Dakle, za gornji niz, maksimalni podniz je {5,1,6}.

Kadenceov algoritam: Susjedni podniz s najvećim zbrojem

Jednostavan pristup rješavanju kontinuiranog podniza najvećeg zbroja

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 sumskog kontinuiranog podniza. Ovo je brutalni pristup jer prolazimo kroz sve moguće podnizove.

Jednostavan pristup rješavanju najvećeg zbroja

Evo jednostavnih koraka za to.

Korak 1) Inicijalizirajte max_sum minimalnom vrijednošću cijelog broja i dodijelite varijablama "begin" i "end" s nulom.

Korak 2) Neka su i i j indeksi niza, gdje je "j" veće od jednakog "i". Predstavlja početni indeks podniza, a "j" predstavlja završni indeks podniza.

Korak 3) “Current_sum” će sadržavati zbroj podniza. Nakon izračunavanja trenutnog zbroja, provjerite je li current_sum veći od max_sum.

Korak 4) Ako je current_sum veći, onda zamijenite max_sum trenutnim zbrojem.

Korak 5) Provjerite dolazi li "j" do kraja niza ili ne. Ako “j” dosegne kraj niza, zatim povećajte “i” i promijenite vrijednost current_sum na 0.

Korak 6) Izvedite sve ove korake, dok "i" ne dođe do kraja niza.

Korak 7) Na kraju ove dvije petlje, max_sum će sadržavati najveću sumu podniza.

Pseudo kod za jednostavan pristup

  function maximumSubarraySum():
    input: array
  for all possible subArray from array:
    calculate sum of each sub array
    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 Primjena 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 sumskog kontinuiranog podniza

Kadaneov algoritam je vrsta metode "dinamičkog programiranja". Ovdje ćemo koristiti jednu petlju umjesto dvije petlje. Opća implementacija Kadaneovog algoritma radi samo za pozitivne nizove brojeva.

Trebaju nam samo dvije varijable da pronađemo najveći sumski susjedni podniz. Evo dijagrama toka za Kadaneov algoritam:

Kadaneov algoritam za pronalaženje najvećeg zbroja

Evo koraka za Kadaneov algoritam:

Korak 1) Napravite dvije varijable, current_sum i max_sum.

“Current_sum” će zadržati vrijednost maksimalnog zbroja koji završava u određenom indeksu polja, dok će “max_sum” pohraniti maksimalnu vrijednost zbroja do sada.

Korak 2) Dodat ćemo vrijednost s current_sum za svaki element niza. Zatim ćemo provjeriti dva uvjeta u nastavku:

  • Ako je current_sum manji od trenutnog elementa, tada će vrijednost current_sum biti trenutni element.
  • Ako je max_sum manji od current_sum, tada će max_sum biti current_sum.

Korak 3) Izvođenjem prethodnog koraka za cijeli niz, imat ćemo najveći zbroj kontinuiranog podniza u varijabli "max_sum".

Primjer Kadaneovog algoritma

Demonstrirat ćemo Kadanesov algoritam s nizom male veličine i raspravljati o svakom koraku pronalaženja najvećeg zbroja susjednog podniza.

Pretpostavimo da je dani niz ovakav:

Primjer Kadaneovog algoritma

Evo koraka Kadaneovog algoritma:

Korak 1) Napravite dvije varijable, current_sum i max_sum. Dodijelite INT_MIN max_sum i nulu current_sum. (Ovdje INT_MIN znači minimalni cijeli broj).

Korak 2) Kod indeksa 0, vrijednost je 4. Dakle, current_sum = 0 + 4 ili 4. Ovdje je current_sum veći od max_sum, max_sum će biti 4.

Primjer Kadaneovog algoritma

Korak 3) Kod indeksa 1 vrijednost je -2. Dakle, current_sum = 4 + (-2) ili 2.

Ovaj put current_sum je manji od max_sum. Kao rezultat toga, vrijednost max_sum neće biti ažurirana.

Primjer Kadaneovog algoritma

Korak 4) Sljedeća vrijednost je 1. Ako ovo zbrojimo s current_sum, tada će current_sum biti 3. Ipak, max_sum je veći od current_sum. Dakle, max_sum neće biti ažuriran.

Primjer Kadaneovog algoritma

Korak 5) Kod indeksa 3, vrijednost je tri. Ažurirat ćemo vrijednost povećanjem current_sum za 3. Dakle, current_sum će biti 6.

Primjer Kadaneovog algoritma

U ovom slučaju, max_sum je manji od current_sum. Dakle, max_sum će se ažurirati s vrijednošću current_sum.

Korak 6) Za zadnji element niza, imamo -1. Ako ovo zbrojimo s current_sum, current_sum će biti 5, što je manje od max_sum. Dakle, max_sum će ostati 6.

Primjer Kadaneovog algoritma

Kako smo došli do kraja niza, algoritam ovdje završava. Sada, "max_sum" sadrži maksimalnu podnizu zbroja. Što je 5. Podniz je {4,-2,1,3}.

Pseudo kod za Kadaneov algoritam

function KadaneAlgorithm():
    input: array
    maximum_sum, current_sum = 0
    for each elements 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 -10000000
  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. Ta metoda izračunava sve moguće zbrojeve podniza kako bi pronašla najveći. To je pristup grube sile. Svaka petlja se izvodi do kraja poredak.

Ako niz ima ukupno N elemenata, tada ćemo pomoću dvije petlje proći kroz N2 elementi. Kao rezultat toga, vremenska složenost za jednostavan pristup za pronalaženje najvećeg zbroja susjednog podniza bit će O(N2). Ovdje "O" označava funkciju složenosti.

S druge strane, Kadaneov algoritam je metoda dinamičkog programiranja za pronalaženje maksimalnog kontinuiranog podniza zbroja. Ako slijedite primjer ili kod, vidjet ćete da koristimo samo jednu petlju.

Kao rezultat toga, ako ulazni niz ima veličinu od N, tada će vremenska složenost Kadaneovog algoritma biti O(N). Ovo je brže od jednostavnog pristupa. Na primjer, niz koji sadrži 100 elemenata. Jednostavan pristup će uzeti 100*100 ili 10,000 100 CPU vremena. Ali Kadaneov algoritam će uzeti samo XNUMX CPU vremena.