This is a continuation to my early complaints about CLRS(3rd edition) if you're looking to learn about algorithms, this is by far the worst book that you can ever use. All the pseudocode examples up to chapter 4 that I've seen so far have mistakes ranging from off by one, wrong/missing base cases for recursive functions, poor design choices that require complete redesign ex: the use of sentinel values in merge sort which is addressed in my other question I mentioned earlier. This book is overhyped and is plain garbage.
In the example shown below, the objective is to find a contiguous subarray with the largest sum.
ex: [13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
sequence: 18, 20, -7, 12
: 43
ex: [4, 5]
sequence: 4, 5
: 9
def max_crossing_subarray(a, low, mid, high):
left_sum = -float('inf')
total = 0
max_left = None
for i in range(mid, low - 1, -1):
total += a[i]
if total > left_sum:
left_sum = total
max_left = i
right_sum = -float('inf')
total = 0
max_right = None
for i in range(mid + 1, high):
total += a[i]
if total > right_sum:
right_sum = total
max_right = i
return max_left, max_right, left_sum + right_sum
def max_subarray(a, low, high):
if high - low == 1: # `high == low` is wrong and results in recursion error
return low, high, a[low]
else:
mid = (low + high) // 2
left_low, left_high, left_sum = max_subarray(a, low, mid)
right_low, right_high, right_sum = max_subarray(a, mid, high)
cross_low, cross_high, cross_sum = max_crossing_subarray(a, low, mid, high)
if left_sum >= right_sum and left_sum >= cross_sum:
return left_low, left_high, left_sum
if right_sum >= left_sum and right_sum >= cross_sum:
return right_low, right_high, right_sum
else:
return cross_low, cross_high, cross_sum
It works for some examples: list size > 2, otherwise, fails:
s1 = [13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
s2 = [2]
s3 = [4, 5]
for s in s1, s2, s3:
print(s)
print(max_subarray(s, 0, len(s)))
print(70 * '=')
Result:
[13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
(7, 10, 43) # correct sum, inclusive indices are correct
======================================================================
[2]
(0, 1, 2) # correct sum, exclusive indices are correct
======================================================================
[4, 5]
(1, 2, 5) # all wrong
======================================================================
Question: code producing wrong/inconsistent results, what's wrong? why? how to fix?
The code given by the book treats low
and high
as inclusive indices. So firstly your call to the method should be
print(max_subarray(s, 0, len(s)-1))
There is no recursion issue with max_subarray()
and the if condition should be left as if low == high:
.
The call for the right half of the subarray should have mid + 1
right_low, right_high, right_sum = max_subarray(a, mid+1, high)
And in max_crossing_subarray()
, the loop condition should be for i in range(mid + 1, high + 1):
.
With all those changes made, the output becomes:
[13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
(7, 10, 43)
======================================================================
[2]
(0, 0, 2)
======================================================================
[4, 5]
(0, 1, 9)
======================================================================