I am working on my python, doing codewars. The description is as follows:
The maximum sum subarray problem consists in finding the maximum sum of a contiguous subsequence in an array or list of integers:
max_sequence([-2, 1, -3, 4, -1, 2, 1, -5, 4]) should be 6: [4, -1, 2, 1]
Easy case is when the list is made up of only positive numbers and the maximum sum is the sum of the whole array. If the list is made up of only negative numbers, return 0 instead.
Empty list is considered to have zero greatest sum. Note that the empty list or array is also a valid sublist/subarray.
Great! Done! here's my code, which passes the tests:
def max_sequence(arr):
sums = []
lists = [[]]
for i in range(len(arr) 1):
for j in range(i):
lists.append(arr[j: i])
for i in lists:
sums.append(sum(i))
return max(sums)
However, for submission, codewars requires you to pass a larger battery of tests, and the tests timeout for larger sets.
In the discussion, many people have the same problem as me. One answer in particular gets to the root of the question, which is what i'm asking here (see the comment below):
Your code is not optmised to work with longer arrays, whilst your code likely works, it takes too long to solve the harder problems so times out. This questions is as much an optimisation problem as any. So you need to find a way to optimise your solution
That is very true for me! What am i doing "wrong" in this data structure, and how can i improve it? My current guesses for the most expensive computations are:
- loop within loop (for i in range.... for j in range i)
- lists.append(arr[j:i])
Any advice? How to improve performance here? I am thinking as much about general data structures and learning as i am about solving this specific question. Thank you!
CodePudding user response:
Reference: https://en.wikipedia.org/wiki/Maximum_subarray_problem#Kadane's_algorithm
You can use Kadane's Algorithm. The idea is that keep adding elements to curr
and get the maximum of curr
and num
. When the sum of the subarray is positive, it keeps going. When the sum of the subarray is negative, it gives up the negative subarray.
You can consider this example with the following code: [-1,1000,-2]
. Initially, curr = -1
. Since it is negative, curr
gives up -1
and gets the value of 1000
. Finally, since 1000
is greater than 998
, it returns 1000
as the answer.
This only has a time complexity of O(n) instead of the brute force approach that has an O(n^3).
def max_sequence(arr):
if not arr or max(arr) < 0:
return 0
curr = max_sub = arr[0]
for num in arr[1:]:
curr = max(num, curr num)
max_sub = max(max_sub, curr)
return max_sub
CodePudding user response:
Similar idea with earlier post, but it tries to bail out earlier when hitting edge cases: (it's still achieved O(n) )
def maxSequence(arr):
if not arr: return 0 # check if it's empty list
if max(arr) < 0: return 0 # check if all negatives
maxx,curr= 0, 0
for x in arr:
curr = x
if curr < 0:
curr = 0
if curr> maxx:
maxx = curr
return maxx