← strona głównaProgramowanie (Програмування)

Jak znaleźć podtablicę o maksymalnej sumie (Maximum Subarray Sum) w Ruby

Rozważmy klasyczny problem z algorytmów: znaleźć podtablicę o maksymalnej sumie. Warunki zadania Mamy tablicę liczb całkowitych (pozytywnych, negatywnych lub zerowych). Należy znaleźć taką ciągłą podsekwencję (subarra...

Spis treściKliknij link, aby przejść do wybranego miejsca
Ta treść została automatycznie przetłumaczona z ukraińskiego.
Rozważmy klasyczny problem z algorytmów: znaleźć podtablicę o maksymalnej sumie.

Warunki zadania

Mamy tablicę liczb całkowitych (pozytywnych, negatywnych lub zerowych). Należy znaleźć taką ciągłą podsekwencję (subarray), której suma jest maksymalna możliwa.
max_sequence([-2, 1, -3, 4, -1, 2, 1, -5, 4])
# => 6, ponieważ największa suma to [4, -1, 2, 1]
Ważne punkty:
  • Jeśli wszystkie liczby są negatywne — zwracamy 0.
  • Pusta tablica również zwraca 0.
  • Podtablica musi być ciągła (to znaczy wszystkie elementy obok siebie).

Zasada rozwiązania (Algorytm Kadane’a)

Będziemy poruszać się po tablicy z lewej do prawej, a na każdym kroku:
  1. Dodajemy bieżącą liczbę do sumy pośredniej current_sum.
  2. Jeśli current_sum stała się mniejsza od 0 — zerujemy ją.
  3. Zapamiętujemy największą wartość current_sum, która się pojawiła — to jest nasza odpowiedź.
Jeśli suma stała się mniejsza od 0, pogarsza ona następne wartości, dlatego ją resetujemy.
Implementacja w Ruby
(jak zawsze, to jedna z możliwych wersji implementacji)
def max_sequence(arr)
  max_sum = 0
  current_sum = 0

  arr.each do |n|
    current_sum += n
    max_sum = [max_sum, current_sum].max
    current_sum = 0 if current_sum < 0
  end

  max_sum
end
Rspec dla metody Ruby
RSpec.describe '#max_sequence' do
  it 'zwraca maksymalną sumę ciągłej podsekwencji' do
    expect(max_sequence([])).to eq(0)
    expect(max_sequence([-1, -2, -3])).to eq(0)
    expect(max_sequence([1, 2, 3])).to eq(6)
    expect(max_sequence([-2, 1, -3, 4, -1, 2, 1, -5, 4])).to eq(6)
    expect(max_sequence([2, -1, 2, 3, 4, -5])).to eq(10)
    expect(max_sequence([-2, -3, 4, -1, -2, 1, 5, -3])).to eq(7)
  end
end

Proste wyjaśnienie

Wyobraźmy sobie, że przechodzimy przez tablicę i gromadzimy sumę. Ale jeśli w pewnym momencie ta suma stała się ujemna — to wszystko, dalej tylko przeszkadza. Resetujemy ją i próbujemy ponownie.
Można wyobrazić sobie, że szukamy najkorzystniejszego odcinka drogi — gdzie zdobyliśmy najwięcej "punktów", nie pozwalając stracić wszystkiego przez jedną złą dziurę.
Ten algorytm nadaje się do problemów typu "znajdź największą podsekwencję". Działa w O(n) — czyli bardzo szybko. Prosty do zaimplementowania i przetestowania.

🔥 Więcej postów

Wszystkie wpisy