19

Could someone take me through what is happening here in Kadane's algorithm? Wanted to check my understanding. here's how I see it.

you are looping through the array, and each time you set the ans variable to the largest value seen, until that value becomes negative, then ans becomes zero.

At the same time, the sum variable is overwritten each time through the loop, to the max between previously seen sums or the largest 'ans' so far. Once the loop is finished executing you will have the largest sum or answer seen so far!

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;

    };
devdropper87
  • 4,025
  • 11
  • 44
  • 70

6 Answers6

19

Consider tracing the values:

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

Prints:

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

The first column is ans, which is the sum of the current subarray. The second is sum, representing the sum of the greatest seen so far. The third is the element that was just visited. You can see that the contiguous subarray with the largest sum is 4, −1, 2, 1, with sum 6.

The example is from Wikipedia.

The following is a translation of the code given in Wikipedia under the paragraph: "A variation of the problem that does not allow zero-length subarrays to be returned, in the case that the entire array consists of negative numbers, can be solved with the following code:" [EDIT: Small bug fixed in the code below]

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;

};

See that:

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

The last number is the expected result. The others are as in the previous example.

Dhruv Batheja
  • 2,140
  • 1
  • 18
  • 16
Dan D.
  • 73,243
  • 15
  • 104
  • 123
  • Awesome I did that and it works perfectly. What's a good way to deal with an array of all negative numbers? I tried adding a max negative tracker and setting/overwriting that inside the loop with a math.min comparison, but if the array was [-10, -11, -12] it would return -12 instead of -10 :/ – devdropper87 Sep 03 '15 at 15:16
  • Implementation is buggy for the array with all negative values. `maximumSubArray([-11, -10, -12]) // gives -11` – Arun Karunagath Apr 24 '18 at 18:21
  • `maximumSubArray([1, 2, 3, -20, 5, 6])` wrongly gives 17. Should be 11. – Om Shankar Aug 03 '18 at 08:20
6

This will take care of both situations mixed array and all negative number array.

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]));
Vinayak Sakhare
  • 768
  • 1
  • 7
  • 14
4

look at this link, it gives a clear explanation for Kadane's algorithm.

Basically you have to look for all positive contiguous segments of the array and also keep track of the maximum sum contiguous segment until the end. Whenever you find a new positive contiguous segment, it checks if the current sum is greater than the max_sum so far and updates that accordingly.

The following code handles the case when all the numbers are negative.

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;
}
akashrajkn
  • 2,295
  • 2
  • 21
  • 47
  • Thanks. What's an efficient way to deal with an array with all negative numbers? Tried following approaches in that link but was unsuccessful. – devdropper87 Sep 03 '15 at 15:14
  • basically you just have to make an extra sweep of all the numbers to check if all the numbers are negative, if that is the case, return the least negative number. – akashrajkn Sep 04 '15 at 10:50
  • @devdropper87 The solution in this answer will handle an all-negative array. Either `curr_max` will find the least-negative `a[i]` and that will be a maximum selected by the `curr_max` argument to the second `max` call, or `a[0]` as the least-negative will be selected (and remain) as maximum in that second `max` call. No need for an extra sweep of all numbers. – Jeff Walden Aug 10 '21 at 11:49
1

I have done enhacement to Kadane's Algorithm for all negative number in an array as well.

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;
    }

Test Case: -30 -20 -10

-10

-10 -20 -30

-10

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

7

amoljdv06
  • 2,646
  • 1
  • 13
  • 18
0
    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 Kadane’s 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; 
} 
        } 
28rox
  • 11
  • 2
-2

I would prefer a more functional way in 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
Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
Mihey Mik
  • 1,643
  • 13
  • 18