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.
If duplicate answers exist, return any of them.
Example
Example 1:
Input: [3, 1, -100, -3, 4]
Output: [4, 1]
Example 2:
Input: [1,-1]
Output: [0, 0]
Challenge
O(n) time
思路:分两段,一段是求没有循环的最大值,另外一段是超过了数组循环里面的最大值,也就是没有超过的最小值;
注意求没有超过的最小值的时候,返回需要从起点是end+1,重点是start-1 , 另外分别还要取模;
public class Solution {
/*
* @param A: An integer array
* @return: A list of integers includes the index of the first number and the index of the last number
*/
public List<Integer> continuousSubarraySumII(int[] A) {
List<Integer> list = new ArrayList<Integer>();
if(A == null || A.length == 0) return list;
int n = A.length;
int totalSum = 0;
for(int i = 0; i < n; i++) {
totalSum += A[i];
}
int[] maxAns = findMax2(A, 1);
int[] minAns = findMax2(A, -1);
if(maxAns[2] > totalSum + minAns[2] || minAns[1] - minAns[0] == n -1) {
list.add(maxAns[0]);
list.add(maxAns[1]);
} else {
list.add((minAns[1] + 1) % n);
list.add((minAns[0] - 1 + n) % n);
}
return list;
}
private int[] findMax2(int[] A, int flag) {
int[] res = new int[3];
int start = 0; int end = 0;
int prefixSum = 0;
int minSum = 0;
int max = Integer.MIN_VALUE;
for(int i = 1; i <= A.length; i++) {
prefixSum += A[i-1] * flag;
if(prefixSum - minSum > max) {
max = prefixSum - minSum;
end = i-1;
res[0] = start;
res[1] = end;
res[2] = max;
}
if(prefixSum < minSum) {
minSum = prefixSum;
start = i;
}
}
return res;
}
}
public class Solution {
/*
* @param A: An integer array
* @return: A list of integers includes the index of the first number and the index of the last number
*/
public List<Integer> continuousSubarraySumII(int[] A) {
List<Integer> list = new ArrayList<Integer>();
if(A == null || A.length == 0) return list;
int n = A.length;
int totalSum = 0;
for(int i = 0; i < n; i++) {
totalSum += A[i];
}
int[] maxAns = findMax(A, 1);
int[] minAns = findMax(A, -1);
if(maxAns[2] > totalSum + minAns[2] || minAns[1] - minAns[0] == n -1) {
list.add(maxAns[0]);
list.add(maxAns[1]);
} else {
list.add((minAns[1] + 1) % n);
list.add((minAns[0] - 1 + n) % n);
}
return list;
}
private int[] findMax(int[] A, int flag) {
int[] res = new int[3];
int start = 0; int end = 0;
int sum = 0;
int max = Integer.MIN_VALUE;
for(int i = 0; i < A.length; i++) {
sum += A[i] * flag;
if(sum > max) {
max = sum;
res[0] = start;
res[1] = i;
res[2] = sum;
}
if(sum < 0){
sum = 0;
start = i+1;
}
}
return res;
}
}