Search code examples
algorithmkadanes-algorithm

Finding number of largest sum sub-arrays in an array using Kadane's algorithm


Kadane's algorithm (http://en.wikipedia.org/wiki/Maximum_subarray_problem) is used to find the largest sum of contiguous sub-array within a one-dimensional array of numbers.

Now, how this be used to find out the number of such sequences that have the same largest sum? What modifications can be done to the algorithm to count such sequences..

For eg:

0 0 0 1     -> (largest sum = 1); 4 sequences  { (0,0,0,1), (0,0,1), (0,1) , (1) }

0 0 0       -> (largest sum = 0); 6 sequences { (0,0,0), (0,0), (0,0), (0), (0), (0) }

2 0 -2 2    -> (largest sum = 2); 4 sequences { (2), (2,0), (2,0,-2, 2), (2) }

Solution

  • Kadane's algorithm keeps track of the maximum value of a sequence ending at the current point, and the maximum value seen so far.

    Here is a Python implementation based on the wikipedia page:

    def kadane(A):
        max_ending_here = max_so_far = 0
        for x in A:
            max_ending_here = max([x,0,max_ending_here+x])
            max_so_far = max(max_so_far,max_ending_here)
        return max_so_far
    

    We can modify the algorithm to keep track of the count of such sequences by adding two variables:

    • count_with_max_ending_here to count the number of sequences ending at the current point with values that sum to max_ending_here
    • count_with_max to count the number of sequences found so far with the maximum value

    Kadane's algorithm can be straightforwardly changed to keep track of these variables while staying at O(n) complexity:

    def kadane_count(A):
        max_ending_here = max_so_far = 0
        count_with_max_ending_here = 0 # Number of nontrivial sequences that sum to max_ending_here
        count_with_max = 0
        for i,x in enumerate(A):
            new_max = max_ending_here+x
            if new_max>=0:
                if count_with_max_ending_here==0:
                    # Start a nontrivial sequence here
                    count_with_max_ending_here=1
                elif max_ending_here==0:
                    # Can choose to carry on a nontrivial sequence, or start a new one here
                    count_with_max_ending_here += 1
                max_ending_here = new_max
            else:
                count_with_max_ending_here = 0 
                max_ending_here = 0
    
            if max_ending_here > max_so_far:
                count_with_max = count_with_max_ending_here
                max_so_far = max_ending_here
            elif max_ending_here == max_so_far:
                count_with_max += count_with_max_ending_here
    
        return count_with_max
    
    for A in [ [0,0,0,1],[0,0,0],[2,0,-2,2] ]:
        print kadane(A),kadane_count(A)