Given an circular integer array (the next element of the last element is the first element), find a continuous subarray in it, where the sum of numbers is the biggest. Your code should return the index of the first number and the index of the last number.
public ArrayList<Integer> continuousSubarraySumII(int[] A) {
ArrayList<Integer> res = new ArrayList<>();
if (A == null || A.length == 0) {
return res;
}
int n = A.length;
int total = 0;
for (int i = 0; i < n; i++) {
total += A[i];
}
int max = findMaxMinRange(A, res, true);// true means find max segment
ArrayList<Integer> res2 = new ArrayList<>();
int min = findMaxMinRange(A, res2, false);// false means find min segment, but the min doesn't have minus in front
int diff = total + min; // total - (-min)
if (diff > max && diff != 0) {// the whole array is minus when diff == 0, so just return res1, which contains the min of all the minus number in the array
int start = (res2.get(1) + 1) % n;
int end = (res2.get(0) - 1) % n;
res.set(0, start);
res.set(1, end);
}
return res;
}
private int findMaxMinRange(int[] A, ArrayList<Integer> res, boolean getMax) {
int max = Integer.MIN_VALUE;
if (!getMax) {
for (int i = 0; i < A.length; i++) {
A[i] = A[i] * -1;
}
}
int s = 0;
int e = 0;
res.add(s);
res.add(e);
int preSum = 0;
for (int i = 0; i < A.length; i++) {
if (preSum < 0) {
preSum = A[i];
s = i;
e = i;
} else {
preSum += A[i];
e = i;
}
if (preSum > max) {
max = preSum;
res.set(0, s);
res.set(1, e);
}
}
return max;
}