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!