Site Search:

find the maximum summary of continuous subarray

Given a N sized integer array, the elements can be positive or negative, one or more continuous elements in the array can form a subarray. Find the subarray with biggest summary. For example, given array {1, -2, 4, 8, -4, 7, -1, -5}, the subarray with max summary is {4, 8, -4, 7}, the maximum value is 15.

Solution:
brutal force solution is to enumerate all the subarrays and count the summary for each one of them. To realize with code, we have an outer loop i iterates through the start index of the subarray and inner loop j iterates through the end index of the subarray, then have a third loop k iterates through the elements in the subarray to count the sum. The time complexity is O(N^3).

Enumerate then sum has lots of redundancy, which can be saved. For example, when summarize {1, -2, 4, 8}, we can use the sum of {1, -2, 4} plus 8. Dynamic programing can help to reduce repeated calculation.

Assuming we have already known the max sum subarray for array arr[1...i - 1], notate the max sum All[i-1]. Now let's add element arr[i] into the picture to see if we got new max sum subarray. There are 3 possible scenarios:

  1. new max sum subarray contains a[i], the new max sum subarray is {<old-max-sum-subarray>, a[i]}, the All[i] = All[i-1] + a[i-1].
  2. new max sum subarray is a[i] itself, the new max sum subarray is {a[i]}, the All[i] = a[i].
  3. old max sum subarray remains unchanged, {<old-max-sum-subarray>}, the All[i] =  All[i-1].
To formalize: All[i] = math.max(All[i - 1] + a[i], a[i], All[i - 1]).

public class maxSubArray {
    public static void main(String...args) {
        int arr[] = new int[] {1, -2, 4, 8, -4, 7};
        System.out.println(maxSubArray(arr));
    }
    //time: O(N), space: O(1)
    public static int maxSubArray(int[] arr) {
        if(arr == null || arr.length < 1) {
            System.out.println("arry is empty");
            return -1;
        }
        
        int nAll = arr[0];
        int nEnd = arr[0];
        for(int i = 1; i < arr.length; i++) {
            nEnd = Math.max(nEnd + arr[i], arr[i]); //no 3 param version in Math.max
            nAll = Math.max(nEnd, nAll);
        }
        return nAll;
    }
}

In order to find the elements of the max sum subarray, we need a new observation. From formula  End[i] = Math.max(End[i - 1] + arr[i], arr[i]), we can find that: whenever End[i-1] < 0, End[i] = arr[i]. If any arr[i-1] makes End[i-1] < 0, the index i - 1 is a potential starting index for the max sum subarray.

public class maxSubArray {
    private int start;
    private int end;
    public static void main(String...args) {
        int arr[] = new int[] {1, -2, 4, 8, -4, 7};
        maxSubArray msa = new maxSubArray();
        System.out.println(msa.maxSubArray(arr));
        System.out.println(msa.start + "," + msa.end);
    }
    //time: O(N), space: O(1)
    public int maxSubArray(int[] arr) {
        int maxSum = Integer.MIN_VALUE;
        int nSum = 0;
        int nStart = 0;
        for(int i = 0; i < arr.length; i++) {
            if(nSum < 0) {
                nStart = i;
                nSum = arr[i];
            } else {
                nSum += arr[i];
            }
            if(nSum > maxSum) {
                maxSum = nSum;
                start = nStart;
                end = i;
            }
        }
        return maxSum;
    }
}