Алгоритъмът на Kadence: Най-голямата сума непрекъснат подмасив

Какъв е най-големият сборен непрекъснат подмасив?

Подмасивът е непрекъсната част от масив. Може да бъде отделен елемент от масив или някаква част от масива. Непрекъснатият подмасив с най-голяма сума означава подмасив, който има максимална сумарна стойност.

Например масивът е {-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} = 11 е максималната сума във всички възможни комбинации от подмасив от горния масив. И така, за горния масив максималният подмасив е {5,1,6}.

Алгоритъмът на Kadence: Най-голямата сума непрекъснат подмасив

Прост подход за решаване на съседен подмасив с най-голяма сума

Простият начин за решаване на този проблем е да използвате два цикъла, за да намерите всички подмасиви, да изчислите сумата и след това да намерите нейната максимална стойност.

Ето блок-схемата за простия подход за намиране на най-голямата сума непрекъснат подмасив. Това е подход на груба сила, тъй като преминаваме през всички възможни подмасиви.

Прост подход за решаване на най-голямата сума

Ето простите стъпки за това.

Стъпка 1) Инициализирайте max_sum с минимална целочислена стойност и задайте променливи „begin“ и „end“ с нула.

Стъпка 2) Нека i и j са индексът на масива, където „j“ е по-голямо от равно на „i“. Той представлява началния индекс на подмасива, а „j“ представлява крайния индекс на подмасива.

Стъпка 3) “Current_sum” ще съдържа сумата на подмасива. След като изчислите текущата сума, проверете дали current_sum е по-голяма от max_sum.

Стъпка 4) Ако текущата_сума е по-голяма, тогава заменете max_sum с текущата сума.

Стъпка 5) Проверете дали „j“ достига края на масива или не. Ако „j“ достигне края на масива, тогава увеличете „i“ и променете стойността на current_sum на 0.

Стъпка 6) Изпълнете всички тези стъпки, докато "i" достигне края на масива.

Стъпка 7) В края на тези два цикъла max_sum ще съдържа най-голямата сума на подмасив.

Псевдо код за прост подход

  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++ Прилагане на прост подход

#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

Алгоритъмът на Кадане за намиране на най-големия сборен непрекъснат подмасив

Алгоритъмът на Кадане е вид метод на "динамично програмиране". Тук ще използваме един цикъл вместо два цикъла. Общата реализация на алгоритъма на Kadane работи само за масиви с положителни числа.

Нуждаем се само от две променливи, за да намерим най-големия сборен съседен подмасив. Ето блок-схемата за алгоритъма на Kadane:

Алгоритъмът на Кадане за намиране на най-голямата сума

Ето стъпките за алгоритъма на Кадане:

Стъпка 1) Създайте две променливи, current_sum и max_sum.

„Current_sum“ ще запази стойността на максималната сума, която завършва в конкретен индекс на масив, докато „max_sum“ ще запази максималната сумирана стойност досега.

Стъпка 2) Ще добавим стойността с текущата_сума за всеки елемент от масива. След това ще проверим две условия по-долу:

  • Ако current_sum е по-малко от текущия елемент, тогава стойността на current_sum ще бъде текущият елемент.
  • Ако max_sum е по-малко от current_sum, тогава max_sum ще бъде current_sum.

Стъпка 3) Изпълнявайки предишната стъпка за целия масив, ще имаме най-голямата сума непрекъснат подмасив в променливата „max_sum“.

Пример за алгоритъм на Кадане

Ще демонстрираме алгоритъма на Каданес с малък по размер масив и ще обсъдим всяка стъпка за намиране на най-големия сборен непрекъснат подмасив.

Да приемем, че даденият масив е като следния:

Пример за алгоритъм на Кадане

Ето стъпките на алгоритъма на Кадане:

Стъпка 1) Създайте две променливи, current_sum и max_sum. Присвоете INT_MIN на max_sum и нула на current_sum. (Тук INT_MIN означава минималното цяло число).

Стъпка 2) При индекс 0 стойността е 4. Така че current_sum = 0 + 4 или 4. Тук current_sum е по-голямо от max_sum, max_sum ще бъде 4.

Пример за алгоритъм на Кадане

Стъпка 3) При индекс 1 стойността е -2. И така, текущата_сума = 4 + (-2) или 2.

Този път текущата_сума е по-малка от максималната_сума. В резултат на това стойността на max_sum няма да бъде актуализирана.

Пример за алгоритъм на Кадане

Стъпка 4) Следващата стойност е 1. Ако добавим това с текущата_сума, тогава текущата_сума ще бъде 3. Все пак максималната_сума е по-голяма от текущата_сума. Така че max_sum няма да се актуализира.

Пример за алгоритъм на Кадане

Стъпка 5) При индекс 3 стойността е три. Ще актуализираме стойността, като увеличим текущата_сума с 3. Така че текущата_сума ще бъде 6.

Пример за алгоритъм на Кадане

В този случай max_sum е по-малък от current_sum. Така че max_sum ще бъде актуализиран със стойността на current_sum.

Стъпка 6) За последния елемент от масива имаме -1. Ако добавим това с current_sum, current_sum ще бъде 5, което е по-малко от max_sum. Така че max_sum ще остане 6.

Пример за алгоритъм на Кадане

Когато стигнахме до края на масива, алгоритъмът свършва тук. Сега „max_sum“ съдържа подмасива с максимална сума. Което е 5. Подмасивът е {4,-2,1,3}.

Псевдокод за алгоритъма на Кадан

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

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

Изход:

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

Анализ на сложността за най-голям сборен непрекъснат подмасив

Простият подход използва два цикъла. Този метод изчислява всички възможни суми на подмасиви, за да намери най-голямата. Това е подход на груба сила. Всеки цикъл се изпълнява до края на масив.

Ако даден масив има общо N елементи, тогава използвайки два цикъла, ще преминем през N2 елементи. В резултат на това времевата сложност за прост подход за намиране на най-голямата сума непрекъснат подмасив ще бъде O(N2). Тук "O" означава функцията на сложността.

От друга страна, алгоритъмът на Кадане е методът за динамично програмиране за намиране на максималния непрекъснат подмасив на сумата. Ако следвате примера или кода, ще видите, че използваме само един цикъл.

В резултат на това, ако входният масив има размер от N, тогава времевата сложност на алгоритъма на Кадан ще бъде O(N). Това е по-бързо от простия подход. Например масив, съдържащ 100 елемента. Простият подход ще отнеме 100*100 или 10,000 100 процесорно време. Но алгоритъмът на Kadane ще отнеме само XNUMX процесорно време.