Алгоритм Кадане

Может ли кто-нибудь взять меня через то, что здесь происходит в алгоритме Кадане? Хотел проверить мое понимание. вот как я это вижу.

вы перебираете массив, и каждый раз, когда вы устанавливаете переменную ans на наибольшее значение, которое видно, до тех пор, пока это значение не станет отрицательным, тогда ans станет нулевым.

В то же время переменная суммы переписывается каждый раз через цикл, до максимума между ранее увиденными суммами или наибольшими "ans" до сих пор. Как только цикл закончен, вы получите самую большую сумму или ответ, увиденный до сих пор!

var sumArray = function(array) {
      var ans = 0;
      var sum = 0;
      //loop through the array.


      for (var i = 0; i < array.length; i++) {
        //this is to make sure that the sum is not negative. 
        ans = Math.max(0, ans + array[i]);

        //set the sum to be overwritten if something greater appears.
        sum = Math.max(sum, ans)
      }

      return sum;

    };

Ответ 1

Рассмотрим трассировку значений:

var maximumSubArray = function(array) {
    var ans = 0;
    var sum = 0;

    console.log(ans, sum);
    for (var i = 0; i < array.length; i++) {

        ans = Math.max(0, ans + array[i]);
        sum = Math.max(sum, ans);
        console.log(ans, sum, array[i]);
    }
    console.log(ans, sum);
    return sum;

};

maximumSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4]);

Печать:

0 0
0 0 -2
1 1 1
0 1 -3
4 4 4
3 4 -1
5 5 2
6 6 1
1 6 -5
5 6 4
5 6

Первый столбец - ans, который является суммой текущего подмассива. Второе - это sum, представляющая сумму самого большого из увиденных до сих пор. Третий элемент, который только что посетил. Вы можете видеть, что непрерывный подмассив с наибольшей суммой равен 4, −1, 2, 1, с суммой 6.

Пример из Википедии.

Ниже приведен перевод кода, приведенного в Википедии под параграфом: "Вариант проблемы, который не позволяет возвращать подмассивы нулевой длины, в случае, если весь массив состоит из отрицательных чисел, может быть решен с помощью следующий код: "[РЕДАКТИРОВАТЬ: небольшая ошибка исправлена в коде ниже]

var maximumSubArray = function(array) {
    var ans = array[0];
    var sum = array[0];

    console.log(ans, sum);
    for (var i = 1; i < array.length; i++) {

        ans = Math.max(array[i], ans + array[i]);
        sum = Math.max(sum, ans);
        console.log(ans, sum, array[i]);
    }
    console.log(ans, sum);
    return sum;

};

Видеть, что:

> maximumSubArray([-10, -11, -12])
-10 -10
-10 -10 -11
-10 -10 -12
-10 -10
-10

Последнее число является ожидаемым результатом. Другие, как в предыдущем примере.

Ответ 2

Это позаботится о смешанном массиве обеих ситуаций и всем массиве отрицательных чисел.

var maximumSubArray = function(arr) {
    var max_cur=arr[0], max_global = arr[0];
    for (var i = 1; i < arr.length; i++) {
        max_cur = Math.max(arr[i], max_cur + arr[i]);
        max_global = Math.max(max_cur, max_global);
    }  
    return max_global;
};
console.log(maximumSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4]));
console.log(maximumSubArray([-10, -11, -12]));

Ответ 3

посмотрите эту ссылку, он дает четкое объяснение алгоритму Кадане.

В основном вам нужно искать все положительные смежные сегменты массива, а также отслеживать максимальный смежный сегмент суммы до конца. Всякий раз, когда вы находите новый положительный смежный сегмент, он проверяет, превышает ли текущая сумма значение max_sum и соответственно обновляет.

Следующий код обрабатывает случай, когда все числа отрицательны.

int maxSubArray(int a[], int size)
{
   int max_so_far = a[0], i;
   int curr_max = a[0];

   for (i = 1; i < size; i++)
   {
        curr_max = max(a[i], curr_max+a[i]);
        max_so_far = max(max_so_far, curr_max);
   }
   return max_so_far;
}

Ответ 4

Я сделал усовершенствование алгоритма Кадане для всех отрицательных чисел в массиве.

int maximumSubSum(int[] array){
        int currMax =0;
        int maxSum = 0;

        //To handle All negative numbers
        int max = array[0];
        boolean flag = true;
        for (int i = 0; i < array.length; i++) {

             //To handle All negative numbers to get at least one positive number
            if(array[i]<0)
                max= Math.max(max , array[i]);
            else
                flag = false;


            currMax = Math.max(0, currMax + array[i]);
            maxSum = Math.max(maxSum , currMax);
        }
        return flag?max:sum;
    }

Тестовый пример: -30 -20 -10

-10

-10 -20 -30

-10

-2 -3 4 -1 -2 1 5 -3

7

Ответ 5

    import java.io.*;  
import java.util.*; 

class Main 
{ 
    public static void main (String[] args) 
    { 
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();    //size
        int a[]=new int[n];     //array of size n
        int i;
        for(i=0;i<n;i++)
        {
            a[i]=sc.nextInt();   //array input
        }

       System.out.println("Largest Sum Contiguous Subarray using Kadanes Algorithm"+Sum(a));
    }

        static int Sum(int a[]) 
{ 

    int max = Integer.MIN_VALUE, max_ending = 0; 

    for (int i = 0; i < size; i++) 
    { 
        max_ending_here = max_ending + a[i]; 
        if (max < max_ending) 
            max = max_ending; //updating value of max
        if (max_ending < 0) 
            max_ending= 0; 
    } 
    return max; 
} 
        } 

Ответ 6

Я бы предпочел более функциональный способ в JavaScript:

const maximumSubArray = function(array) {
  return array.reduce(([acc, ans], x, i) => { 
    ans = Math.max(0, ans + x);
    return [Math.max(acc, ans), ans];
  }, [array[0],array[0]])[0];
};

cl(maximumSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4])); // 6