Our treatment of this problem is taken from Chapter 8 of the book Programming Pearls, second edition, by Jon Bentley. The chapter and the book are wonderful to read, and I highly recommend them. The author provides a brief sketch of the chapter in the form of lecture notes in PDF format, as well as the source code for the algorithms (in C), together with a convenient driver.
I offer my own Python implementation and test harness.
This problem is also introduced in Chapter 4.1 of CLRS, with a
presentation of the
The problem is to take as input an array of n values (some of which may be negative), and to find a contiguous subarray which has the maximum sum. For example, consider the array:
31 | -41 | 59 | 26 | -53 | 58 | 97 | -93 | -23 | 84 |
We consider five distinct algorithms for solving this problem.
maxsofar = 0; for (i = 0; i < n; i++) for (j = i; j < n; j++) { sum = 0; for (k = i; k <= j; k++) sum += A[k]; if (sum > maxsofar) maxsofar = sum; }
maxsofar = 0; for (i = 0; i < n; i++) { sum = 0; for (j = i; j < n; j++) { sum += A[j]; // sum is that of A[i..j] if (sum > maxsofar) maxsofar = sum; } }
maxsofar = 0; cumarr[-1] = 0; for (i = 0; i < n; i++) cumarr[i] = cumarr[i-1] + A[i]; for (i = 0; i < n; i++) { for (j = i; j < n; j++) { sum = cumarr[j] - cumarr[i-1]; // sum is that of A[i..j] if (sum > maxsofar) maxsofar = sum; } }
The toplevel recursion is invoked as recmax(0,n-1).float recmax(int l, int u) if (l > u) /* zero elements */ return 0; if (l == u) /* one element */ return max(0, A[l]); m = (l+u) / 2; /* find max crossing to left */ lmax = sum = 0; for (i = m; i ≥ l; i--) { sum += A[i]; if (sum > lmax) lmax = sum; } /* find max crossing to right */ rmax = sum = 0; for (i = m+1; i ≤ u; i++) { sum += A[i]; if (sum > rmax) rmax = sum; } return max(max(recmax(l, m), recmax(m+1, u)), lmax + rmax); }
maxsofar = 0 maxendinghere = 0; for (i = 0; i < n; i++) { maxhere = max(maxhere + A[i], 0) maxsofar = max(maxsofar, maxhere) }