Problem: Given an array of N integers (both positive and negative), find the sub-sequence with largest sum.
For ex: Let A = {1 2 -5 4 5 -1 2 -11} then largest sum is 10 (start = 4, end = 7)
Solution:
show
The naive solution to this problem can be formulated and coded in O(N^3) time. Consider every possible pair of start and end index and calculate sum of the elements within those index and keep track of the max sum. The following code performs that
max = - Inf
imax = jmax = -1
for i = 1 to N
for j = i to N
// get sum of elements enclosed in index (i,j)
s = 0
for k = i to j
s += A[k]
if s > max
max = s
imax = i
jmax = j
Clearly the above algorithm is O(N^3). We can definitely improve the running time of the above algorithm. After observing carefully, we can see that an operation that is run several times (O(N^2) times) is computing the sum of elements between indices i,j. Can we do it quickly. Indeed we can.
If we save the cumulative sum of elements in an array CSUM, then CSUM[i] indicates the sum of elements enclosed in indices (1,i), CSUM[j]-CSUM[i-1] would then indicate the sum of elements enclosed in indices (i,j). The following algorithm captures this intuition.
csum[0] = 0
for i = 1 to N
csum[i] = csum[i-1] + A[i]
max = - Inf
imax = jmax = -1
for i = 1 to N
for j = i to N
s = CSUM[j] - CSUM[i-1]
if s > max
max = s
imax = i
jmax = j
This is the best we can do with this approach. This problem can be done in O(N) time using a clever approach. Consider a sub-sequence with sum s > 0. Let the next element n is such that s + n < 0. Clearly this sub-sequence cannot be part of largest subsequence that contains s and n as removing s,n from that sub-sequence we get a larger sum. Easy to prove using contradiction. This idea is captured in the following O(N) algorithm
max = -Inf
imax = jmax = -1
i_temp = -1
s_temp = 0
for i = 1 to N
s_temp += A[i]
if s_temp > max
// keep track of max so far
max = s_temp
imax = i_temp
jmax = i
if s_temp < 0
// abort this sub-sequence
s_temp = 0
i_temp = i + 1
Problem: Given an array of N integers (both positive and negative), find the sub-sequence with largest
absolute sum. This problem differs from the one at the top as we want the absolute sum (taking mod)
For ex: Let A = {1 2 -5 4 5 -1 2 -11} then largest absolute sum is 11.
Solution:
show
Simply keep track of max and min at the same time in the above O(N) solution.
Assuming that we have to use the above algorithm without modification, then we can take these steps to get max absolute sum in O(N) time:
1. Run O(N) algorithm on array A to get the max
2. Create array B by multiply all numbers in A by -1
3. Run O(N) algorithm on array B to get the max
4. Pick the max between the output of two runs of the algorithm
Instead of trying the above two methods, we can try a very nice and simple approach
// build csum matrix as before
csum[0] = 0
for i = 1 to N
csum[i] = csum[i-1] + A[i]
answer = max(csum) - min(csum)
The answer is maximum element of csum minus the minimum element of csum.
Hi can you please point out how max will work for absolute sum. Say if we have sequence A = {1 2 -5 4 5 -1 -2 -11}. Then the absolute sum is -14. Instead using something similar to part a) whenever sum(not absolute) and current element are of opposite sign just ignore the previous sequence since two opposite signs will always decrease the magnitude.
ReplyDelete