1

I've tried to find the sub-array(s) from a given which contain elements of maximum sum than any other sub array.

Below function has parameter as input a and the output needs to be returned. There can be more than one subarray as their maximum sum can be equal. The code did not seem to be working as expected.

def max_sum_subarray(a):
        N, sub_sum, max_sum, subArrays = len(a), 0, 0, {}
        p,q=0,0    #starting and ending indices of a max sub arr

        for i in range(N):
            q=i
            sub_sum+=a[i]

            if(a[i]<0):
                q-=1
                if(sub_sum>=max_sum):
                    if(sub_sum>max_sum):
                        subArrays.clear()
                        subArrays[sub_sum]=[(p,q)]
                    else:
                        subArrays[sub_sum].append((p,q))

                sub_sum=0
                p=i+1

        if(sub_sum>=max_sum):
            if(sub_sum>max_sum):
                subArrays.clear()
                subArrays[sub_sum]=[(p,q)]
            else:
                subArrays[sub_sum].append((p,q))
        return(subArrays[p:q+1])


When I tried to run for input

a=[ 1, 2, 5, -7, 2, 5 ]

Expected output is [1, 2, 5] but it gave [2, 5] instead. Can anyone please post the solution in python?

  • Mind explaining the algorithm you've implemented? – Nir Alfasi Jul 14 '19 at 07:23
  • subArrays is a dict, when running your code I get `TypeError: unhashable type: 'slice'` on the `return` line... – Adam.Er8 Jul 14 '19 at 07:26
  • Aproach is, start from the first index and keep on adding the sum until you find a negative element, from now on start adding the sum from zero, but also maintain the maximum sums. Here, I created a dictionary updating key as so far maximum sum and value as so far required sub-array's starting and ending index. – Krishna Vamshi Chintala Jul 14 '19 at 07:29

2 Answers2

3

It seems like you making this harder than necessary. You can just keep track of max array seen to far and the current one you're pushing into -- you don't really need to care about anything else. When you hit a negative (or the end of the array) decide if the current should be the new max:

def maxSub(a):
    max_so_far = []
    max_sum = 0
    cur = []
    for n in a:
        if n >= 0:
            cur.append(n)
        else:
            cur_sum = sum(cur)
            if cur_sum > max_sum:
                max_sum = cur_sum
                max_so_far = cur
            cur = []

    return max([max_so_far, cur], key = sum)


a=[ 1, 2, 5, -7, 2, 5 ]

maxSub(a)
# [1, 2, 5]

Of course itertools.groupby makes this a one-liner:

from itertools import groupby

a=[ 1, 2, 5, -7, 2, 5 ]
max([list(g) for k,g in groupby(a, key=lambda x: x>0) if k == True], key=sum)
Mark
  • 90,562
  • 7
  • 108
  • 148
  • I like `groupby` approach. Also you don't need `cur` list, just remember first positive index and go `cur_sum = sum(a[firstPositive:n])`, performance will be actually even faster. – Radosław Cybulski Jul 14 '19 at 07:47
  • Yeah, that's a good tip @RadosławCybulski — thanks. Never sure how to balance clarity of concept and efficiency on answers here. – Mark Jul 14 '19 at 07:49
  • 1
    The same here, obvious things for me doesn't seem so obvious after i type it. This is actually why i like answering on SO, as it forces me to rethink everything i write in context of reader. – Radosław Cybulski Jul 14 '19 at 07:50
  • This will accept form some TC's only. for TC [ 0, 0, -1, 0] expected op is 0 0 and it gives just 0 so for this use Sliding windows concept. – Shantanu Gupta Jun 03 '21 at 09:32
  • @ShantanuGupta is the sum of `[0, 0]` greater than the sum of `[0]`? Why is one preferred over the other? – Mark Jun 04 '21 at 16:09
  • @mark second condition is if any two streak sum is equal then compare their length and return longest length. here `[0, 0]` and `[0]` sum is 0 but length of `[0, 0]` is long that's why have to return [0, 0] – Shantanu Gupta Jun 06 '21 at 14:54
  • @ShantanuGupta Maybe it's just too early, but I don't see that second condition anywhere in the question. Where does it say that? The only place the words `length` or `longest` appear on this page is in your comment. – Mark Jun 06 '21 at 14:57
  • [0, 0, -1, 0] is one of TC in lnterviewBit. – Shantanu Gupta Jun 06 '21 at 14:58
0

For the following conditions:

NOTE 1: If there is a tie, then compare with segment’s length and return segment which has maximum length

NOTE 2: If there is still a tie, then return the segment with minimum starting index

Here is my working code in python:

def check(max_arr,curr):
    if sum(curr) > sum(max_arr):
        max_arr = curr
    elif sum(curr) == sum(max_arr):
        if len(curr) > len(max_arr):
            max_arr = curr
        elif len(curr) == len(max_arr):
            if max_arr and (curr[0] > max_arr[0]):
                max_arr = curr
    return max_arr

def maxset(A):
    curr = []
    max_arr = []
    for i in A:
        if i >= 0:
            curr.append(i)
        else:
            max_arr = check(max_arr,curr)
            curr = []
    max_arr = check(max_arr,curr)                    
    return max_arr