/** * Find two disjoint (non-overlapping) subsequences in an array with maximum * difference. * * Tags: Array */ class MaxSubseqDifferenceNoOverlap { public static void main(String[] args) { } /** * Cut input array in two halves * Find max contiguous subsequences sum in left half, min sum in right half * Find max contiguous subsequences sum in right half, min sum in left half * Get the two differences, the bigger one can be max difference * Update maxDiff and range with that */ public int MaxSubseqDifferenceNoOverlap(int[] A) { int[] finalMax = null; // subsequences int[] finalMin = null; Integer maxDiff = null; // use Integer to determine whether it's set for (int i = 0; i < A.length; i++) { int[] preMax = maxKadane(A, 0, i); // left max int[] postMin = minKadane(A, i, A.length); // right min int[] preMin = minKadane(A, 0 ,i); // left min int[] postMax = maxKadane(A, i, A.length); // right max int diff1 = sum(A, preMax) - sum(A, postMin); int diff2 = sum(A, postMax) - sum(A, preMin); if (diff1 > diff2) { // if maxDiff not set or diff1 is bigger if (maxDiff == null || diff1 > maxDiff) { // update maxDiff maxDiff = diff1; finalMax = preMax; finalMin = postMin; } } else { if (maxDiff == null || diff2 > maxDiff) { maxDiff = diff2; finalMax = postMax; finalMin = preMin; } } } return maxDiff; } /** * */ private int[] maxKadane(int[] A, int s, int e) { int beginTemp = s; int begin = s; int end = s; int maxSoFar = A[s]; int maxEndingHere = A[s]; for (int i = 1; i < e; i++) { if (maxEndingHere < 0) { maxEndingHere = A[i]; beginTemp = i; } else maxEndingHere += A[i]; if (maxEndingHere >= maxSoFar) { maxSoFar = maxEndingHere; begin = beginTemp; end = i; } } return new int[]{begin, end}; } /** * Modification of */ private int[] minKadane(int[] A, int s, int e) { int beginTemp = s; int begin = s; int end = s; int minSoFar = A[s]; int minEndingHere = A[s]; for (int i = 1; i < e; i++) { if (minEndingHere > 0) { minEndingHere = A[i]; beginTemp = i; } else minEndingHere += A[i]; if (minEndingHere <= minSoFar) { minSoFar = minEndingHere; begin = beginTemp; end = i; } } return new int[]{begin, end}; } private int sum(int[] A, int[] range) { int sum = 0; for (int i = range[0]; i <= range[1]; i++) { sum += A[i]; } return sum; } }