Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

maximum subarray of an array with integers [duplicate]

Tags:

algorithm

In an interview one of my friends was asked to find the subarray of an array with maximum sum, this my solution to the problem , how can I improve the solution make it more optimal , should i rather consider doing in a recursive fashion ?

def get_max_sum_subset(x):
        max_subset_sum = 0
        max_subset_i = 0
        max_subset_j = 0
        for i in range(0,len(x)+1):
            for j in range(i+1,len(x)+1):
                current_sum = sum(x[i:j])
                if current_sum > max_subset_sum:
                    max_subset_sum = current_sum
                    max_subset_i = i
                    max_subset_j = j
        return max_subset_sum,max_subset_i,max_subset_j
like image 870
Bunny Rabbit Avatar asked Oct 30 '11 08:10

Bunny Rabbit


4 Answers

Your solution is O(n^2). The optimal solution is linear. It works so that you scan the array from left to right, taking note of the best sum and the current sum:

def get_max_sum_subset(x):
    bestSoFar = 0
    bestNow = 0
    bestStartIndexSoFar = -1
    bestStopIndexSoFar = -1
    bestStartIndexNow = -1
    for i in xrange(len(x)):
        value = bestNow + x[i]
        if value > 0:
            if bestNow == 0:
                bestStartIndexNow = i
            bestNow = value
        else:
            bestNow = 0

        if bestNow > bestSoFar:
            bestSoFar = bestNow
            bestStopIndexSoFar = i
            bestStartIndexSoFar = bestStartIndexNow

    return bestSoFar, bestStartIndexSoFar, bestStopIndexSoFar

This problem was also discussed thourougly in Programming Pearls: Algorithm Design Techniques (highly recommended). There you can also find a recursive solution, which is not optimal (O(n log n)), but better than O(n^2).

like image 153
Antti Avatar answered Oct 17 '22 04:10

Antti


This is a well-known problem that displays overlapping optimal substructure, which suggests a dynamic programming (DP) solution. Although DP solutions are usually quite tricky (I think so at least!), this one is a great example to get introduced to the whole concept.

The first thing to note is that the maximal subarray (which must be a contiguous portion of the given array A) ending at position j either consists of the maximimal subarray ending at position j-1 plus A[j], or is empty (this only occurs if A[j] < 0). In other words, we are asking whether the element A[j] is contributing positively to the current maximum sum ending at position j-1. If yes, include it in the maximal subarray so far; if not, don't. Thus, from solving smaller subproblems that overlap we can build up an optimal solution.

The sum of the maximal subarray ending at position j can then be given recursively by the following relation:

sum[0] = max(0, A[0])
sum[j] = max(0, sum[j-1] + A[j])

We can build up these answers in a bottom-up fashion by scanning A from left to right. We update sum[j] as we consider A[j]. We can keep track of the overall maximum value and the location of the maximal subarray through this process as well. Here is a quick solution I wrote up in Ruby:

def max_subarray(a)
    sum = [0]
    max, head, tail = sum[0], -1, -1
    cur_head = 0

    (0...a.size).each do |j|
        # base case included below since sum[-1] = sum[0]
        sum[j] = [0, sum[j-1] + a[j]].max
        cur_head = j if sum[j-1] == 0
        if sum[j] > max
            max, head, tail = sum[j], cur_head, j
        end
    end

    return max, head, tail
end

Take a look at my gist if you'd like to test this for yourself.

This is clearly a linear O(N) algorithm since only one pass through the list is required. Hope this helps!

like image 27
pdsouza Avatar answered Oct 17 '22 05:10

pdsouza


let n - elements count, a(i) - your array f(i) - maximum sum of subarray that ends at position i (minimum length is 1). Then:

f(0) = a(i);
f(i) = max(f(i-1), 0) + a(i); //f(i-1) when we continue subarray, or 0 - when start at i position

max(0, f(1), f(2), ... , f(n-1)) - the answer

like image 5
Ivan Bianko Avatar answered Oct 17 '22 03:10

Ivan Bianko


A much better solution approach can be derived by thinking about what conditions must hold for a maximum-sum sub-array: the first item on either end that is not included (if any) must be negative and the last item on either end that is included must be non-negative. You don't need to consider any other end points for the sub-array except where these changes occur in the original data.

like image 5
Ted Hopp Avatar answered Oct 17 '22 05:10

Ted Hopp