This is an exercise in implementing the maximum sub-array sum problem.
It asks for several solutions of complexity:
- \$O(n)\$
- \$O(n \log n)\$
- \$O(n^2)\$
- \$O(n^3)\$
For an additional challenge I completed it using Python.
import random
import timeit
#random array generator
def generate_array(item_count, lower_bound, upper_bound):
number_list = []
for x in range(1, item_count):
number_list.append(random.randint(lower_bound, upper_bound))
return number_list
#cubic brute force O(n^3)
def max_subarray_cubic(array):
maximum = float('-inf')
for i in range(1, len(array)):
for j in range(i, len(array)):
current_sum = 0
for k in range(i, j):
current_sum += array[k]
maximum = max(maximum, current_sum)
return maximum
#quadratic brute force O(n^2)
def max_subarray_quadratic(array):
maximum = float('-inf')
for i in range(0, len(array)):
current = 0
for j in range(i, len(array)):
current += array[j]
maximum = max(current, maximum)
return maximum
#divide and conquer O(n*lg(n))
def max_cross_sum(array, low, mid, high):
left_sum = float('-inf')
sum_ = 0
for i in range(mid, low, -1):
sum_ += array[i]
left_sum = max(left_sum, sum_)
right_sum = float('-inf')
sum_ = 0
for i in range(mid + 1, high):
sum_ += array[i]
right_sum = max(right_sum, sum_)
return left_sum + right_sum
def max_subarray_div_conquer(array, low, high):
if low == high:
return array[low]
else:
mid = (low + high) / 2
return max(max_subarray_div_conquer(array, low, mid),
max_subarray_div_conquer(array, mid + 1, high),
max_cross_sum(array, low, mid, high))
#Kadane's algorithm O(n)
def max_subarray_kadane(array):
current = maximum = array[0]
for x in array[1:]:
current = max(x, current + x)
maximum = max(maximum, current)
return maximum
#to facilitate timing each algorithm
def function_timer(function, array, policy):
start_time = timeit.default_timer()
if policy == "divide and conquer":
print("Maximum sub sum for the %s algorithm: %s"
% (policy, function(array, 0, len(array) - 1)))
else:
print("Maximum sub sum for the %s algorithm: %s" % (policy, function(array)))
print("Running Time: %s seconds.\n" % (timeit.default_timer() - start_time))
magnitude = input('enter vector size: ')
number_list = generate_array(magnitude, -10, 10)
function_timer(max_subarray_cubic, number_list, "cubic")
function_timer(max_subarray_quadratic, number_list, "quadratic")
function_timer(max_subarray_div_conquer, number_list, "divide and conquer")
function_timer(max_subarray_kadane, number_list, "kadane")
I would like:
- To know if this is Pythonic? Am I accurately following conventions?
- A general review on the accuracy of the algorithms. To the best of my knowledge I completed the requirements, but just in case. Focusing on the divide and conquer algorithm as it heavily differs and the cubic solution, it's surprisingly difficult to think about how to solve something poorly.
- Feedback on the way I measure running time. I gave myself a means to run tests but how effective is it? How reliable are the results?