CIS 301. Minimal-sum section problem.

Minimal-sum section.


We consider an integer array a[1..n] of length n. A section of a[1..n] is a sub-array a[i..j] of a[1..n] that has "no gaps". For example, the array [-2,3,-6,7,-8,5,-6] has length 7, and some of its sections are

Note that [-2,-6] is not a section of that array, for 3 is missing. Also, [-6,9,7] is not a section, since 9 is not in the original array. For any section of an array, we can form its sum. For example, the sum of [-6,7,-8,5] is -6 + 7 - 8 + 5 = -2, and the sum of [3] is 3.


The minimal-sum section problem is this:

Given an array a[1..n] of length n, compute the sum of one of its sections with minimal sum.

In the example above, there is only one section that has a minimal sum, the section [-8,5,-6], with sum -9. An array can have multiple sections with minimal sum. For example, the array [-9,12,-2,3,-6,7,-8,5,-6] has two sections, [-9] and [-8,5,-6] with minimal sum -9.

There is a naive computational solution to this problem:

This approach, if carried out properly, results in a correct solution to the problem. However, it won't be of practical use for reasonably big arrays. For example, if you had to look through an array of one million integer entries, this algorithm would require non-trivial computation steps of the order 1,000,000,000,000,000,000. Fortunately, one can come up with a really slick problem decomposition and its corresponding invariants such that we can compute this minimal-sum section in linear time (i.e. the program only has to read the entire array once). We present the code for this approach before discussing its idea. This should illustrate that understanding other people's code without any documentation of the involved ideas may be quite difficult (implying that you should always take time to include insightful comments into your source code).
  k = 2;
  t = a[1];
  s = a[1];
  while (k != n + 1) {
     t = min(t + a[k], a[k]);
     s = min(s,t);
     k = k + 1;
  }
Ignoring the construct for array-field access above, this program is written in our core programming language and we mean to show its partial (and later on its total) correctness. If we write this program, say, in Java, we add the usual language-specific jargon, but the essence of the algorithm, and our correctness argument prevail. A possible Java code for this algorithm is:
public class Sum_Section {

  private static KeyboardReader keyboard = new KeyboardReader();

  public static void main(String[] args) {

    int n;

    do { n = keyboard.readInt("number of entries in the array ( > 1): "); }
    while (n <= 1);

    int[] a = new int[n+1];              // we won't use a[0]

      for (int i = 1; i < n+1; ++i) {
        a[i] = keyboard.readInt("array entry number " + i + ": ");
      }

    int t = a[1];
    int s = a[1];
    System.out.println("initial t = " + t + " and initial s = " + s);

    for (int k = 2; k != n+1; ++k) {
      
      if (t+a[k] < a[k]) { t = t+a[k]; }
      else { t = a[k]; }
    
      if (t < s) { s = t; }
      System.out.println("t = " + t + " and s = " + s);
   }

    System.out.println("The sum of a minimal sum-section is " + s);
  }
}
We consider a run of this program:


nunk% java Sum_Section
number of entries in the array ( > 1): 8
array entry number 1: 4
array entry number 2: -8
array entry number 3: 3
array entry number 4: -4
array entry number 5: 8
array entry number 6: -6
array entry number 7: -3
array entry number 8: 5
initial t = 4 and initial s = 4
t = -8 and s = -8
t = -5 and s = -8
t = -9 and s = -9
t = -1 and s = -9
t = -7 and s = -9
t = -10 and s = -10
t = -5 and s = -10
The sum of a minimal sum-section is -10
This run demonstrates that determining a minimal-sum section "by hand" may to tricky. Indeed, our textbook (Example 4.14, page 253) claims that the array above has two minimal-sum sections with value -9. As our program shows, this is incorrect!


We now reason informally why our core program is correct:

  k = 2;
  t = a[1];
  s = a[1];
  while (k != n + 1) {
     t = min(t + a[k], a[k]);
     s = min(s,t);
     k = k + 1;
     // invariant1: t is the minimal-sum of all sections that end with a[k-1]
     // invariant2: s is the minimal-sum of all sections in the array a[1..k-1]
  }


Michael Huth (huth@cis.ksu.edu)