Największa suma podlisty listy jest zadanie, które polega na zsumowaniu k kolejnych elementów, aby otrzymać jak największą sumę. Na liście znajduje się zarówno liczby dodatnie jak i ujemne. Zadanie można rozwiązać algorytmem naiwnym, który sprawdzi wszystkie poprawne podlisty. Istnieje jednak algorytm Kadanego, który znacząco przyśpiesza proces.
Przykładowo dla listy L := {1, -2, 3, 1, 5} największą sumą podlisty jest suma elementów podlisty {3, 1, 5} = 9.
Warto jednak zauważyć, że w przypadku, że gdyby na pierwszej pozycji była wartość > 2 to największa wartość powstałaby poprzez zsumowanie wszystkich elementów. Przykładowo, gdy L := {8, -2, 3, 1, 5} to największa suma elementów podlisty wynosi już nie 9, a 15.
Dla listy o długości n podczas szukania naiwnego najpierw należałoby zsumować wszystkie elementy, a następnie zmniejszać długość podlisty o 1 i ponownie zsumować wszystkich podlist o długości n - 1. Oznacza to, że łącznie podlist będzie 1 + 2 + .. + (n - 1) + n = 0.5·(n + 1)·n = 0.5·(n2 + n). Oznacza to, że złożoność obliczeniowa wynosi Θ(n2). Poniżej został zamieszczony kod realizujący to zadanie:
(1.) Funkcja przyjmuje dwa argumenty: lista - lista liczb całkowitych oraz n - długość listy. (2.) Początkowo należy przyjąć, że maksymalna suma wynosi tyle co pierwszy element. (3.) Zadeklaruj zmienną suma, która będzie używana podczas sumowania wybranej podlisty. (4.) Dla każdej długości podlisty: (5.) Dla każdej podlisty o długości i: (6.) zresetuj suma i (7. - 9.) zsumuj elementy tej podlisty, a następnie (10.) sprawdź czy nowa suma jest większa od dotychczas znalezionego maksimum. Jeśli tak to (11.) zastąp tę wartość. Po wykonaniu wszystkich pętli należy zwrócić (15.) wartość zmiennej max.
Algorytm Kadanego to bardzo sprytne zauważenie prawidłowości zachodzących podczas sumowania kolejnych elementów. Przede wszystkim lista L := {1, -2, 3, 1, 5} jest równoważna w przypadku szukania maksymalnej sumy elementów podlisty L' := {1, -2, 9}. Algorytm rozpoczyna sumowanie od pierwszego elementu. Następnie do aktualnej sumy dodaje następny element z listy. W przypadku, gdy suma spadnie poniżej zera to algorytm zeruje sume. Jednak w przypadku, gdy suma jest dodatnia to należy sprawdzić czy nie jest większa od dotychczasowego maksimum. Za początkowe maksimum można przyjąć pierwszy element.
Złożoność obliczeniowa tego algorytmu to Θ(n), ponieważ każdy element jest pobierany i dodawany dokładnie jeden raz.
Przykładowo dla L' := {1, -2, 9} algorytm kolejno wykona:
Maksimum | Suma | i-ty element | Komentarz |
---|---|---|---|
1 | 0 | 1 | snowa = 1, nie jest większa od maksimum |
1 | 1 | -1 | snowa = -1, jest mniejsza od zera, więc suma jest resetowana na 0 |
1 | 0 | 9 | snowa = 9, jest większa od maksimum, więc zostaje ustalone nowe maksimum |
W podanym przykładzie największa suma podlisty wynosi 9.
Warto rozważyć jeszcze jeden przypadek, który pokaże, że algorytm uwzględnia w sumie wartości ujemne, a nie szuka tylko maksimum wśród podlist złożonych z samych liczb dodatnich.
Przykładowo dla L' := {2, -1, 3, -2, -5, 1} algorytm kolejno wykona:
Maksimum | Suma | i-ty element | Komentarz |
---|---|---|---|
2 | 0 | 2 | snowa = 2, nie jest większa od maksimum |
2 | 2 | -1 | snowa = 1, nie jest większa od maksimum |
2 | 1 | 3 | snowa = 4, jest to nowa wartość maksimum |
4 | 4 | -2 | snowa = 2, nie jest większa od maksimum |
4 | 2 | -5 | snowa = -3, jest mniejsza od zera, więc suma jest resetowana na 0 |
4 | 0 | 1 | snowa = 1, nie jest większa od maksimum |
W podanym przykładzie największa suma podlisty wynosi 4.
(2.) Przyjmij za maksimum 0 i wyzeruj początkową sumę elementów. (3.) Dla każdego elementu listy: (4.) wylicz nową sumę i (5.) sprawdź czy nowa suma jest większa od maksimum. Jeśli tak to (6.) zmień wartość maksimum. Następnie (8.) sprawdź czy nowa suma jest mniejsza od zera. Jeśli tak to (9.) wyzeruj sumę. Ten fragment kodu "wybiera", które podlisty złożone z samych liczb dodatnich zsumować pomimo ujemnych elementów pomiędzy nimi.
W celu przetestowania działania funkcji można skorzystać z funkcji maxSubListTEST(), która przyjmuje te same argumenty co funkcja maxSubList(). Funkcja ta wypisuje na ekranie komunikaty zrozumiałe dla programisty.
Wykorzystanie funkcji maxSubListTEST() prezentuje poniższy kod:
Napisz funkcję, która znajdzie minimalną wartość sumy elementów na podanej liście o długości n. Przyjmuje, że pod lista to kolejne k elementy z listy. Nagłówek funkcji powinien być następujący: int minSubList(int* lista, int n).
Przykładowo dla listy L:={-1, -2, 3, -3, -5} minimalna suma elementów wybranej podlisty wynosi -8.