Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [-2,1,-3,4,-1,2,1,-5,4]
,
the contiguous subarray [4,-1,2,1]
has the largest sum = 6
.
More practice:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
class Solution {
public int maxSubArray(int[] nums) {
int tmp = nums[0], res = nums[0];
for (int i = 1; i < nums.length; i ++) {
tmp = nums[i] + (tmp > 0 ? tmp : 0);
res = Math.max(tmp, res);
}
return res;
}
}
算法1:二重循环,复杂度O(n²)
import java.util.Scanner;
public class MaxSubSum1 {
public static int maxSubSum(int[] array) {
int thisSum, maxSum = 0;
for (int i = 0; i < array.length; i ++) {
thisSum = 0;
for (int j = i; j < array.length; j ++) {
thisSum += array[j];
if (thisSum > maxSum)
maxSum = thisSum;
}
}
return maxSum;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int[] array = new int[num];
for (int i = 0; i < num; i ++) {
array[i] = in.nextInt();
}
System.out.println(MaxSubSum1.maxSubSum(array));
}
}
算法2:分治,复杂度O(nlogn)
import java.util.Scanner;
public class MaxSubSum2 {
public static int maxSubSum(int[] array, int N) {
return divideAndConquer(array, 0, N - 1);
}
public static int max(int a, int b, int c) {
int max1 = a > b ? a : b;
return max1 > c ? max1 : c;
}
public static int divideAndConquer(int[] array, int left, int right) {
if (left == right) {
if (array[left] > 0)
return array[left];
else
return 0;
}
int center = (left + right) / 2;
int maxLeftSum = divideAndConquer(array, left, center);
int maxRightSum = divideAndConquer(array, center + 1, right);
int maxLeftBorderSum = 0, leftBorderSum = 0;
for (int i = center; i >= left; i --) {
leftBorderSum += array[i];
if (leftBorderSum > maxLeftBorderSum)
maxLeftBorderSum = leftBorderSum;
}
int maxRightBorderSum = 0, rightBorderSum = 0;
for (int i = center + 1; i <= right; i ++) {
rightBorderSum += array[i];
if (rightBorderSum > maxRightBorderSum)
maxRightBorderSum = rightBorderSum;
}
return max(maxLeftSum, maxRightSum, maxLeftBorderSum +
maxRightBorderSum);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int[] array = new int[num];
for (int i = 0; i < num; i ++) {
array[i] = in.nextInt();
}
System.out.println(MaxSubSum2.maxSubSum(array, num));
}
}
算法3:在线实现,复杂度O(n)
import java.util.Scanner;
public class MaxSubSum3 {
public static int maxSubSum(int[] array, int N) {
int thisSum = 0, maxSum = 0;
for (int i = 0; i < N; i ++) {
thisSum += array[i];
if (thisSum > maxSum)
maxSum = thisSum;
else if (thisSum < 0)
thisSum = 0;
}
return maxSum;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int[] array = new int[num];
for (int i = 0; i < num; i ++) {
array[i] = in.nextInt();
}
System.out.println(MaxSubSum3.maxSubSum(array, num));
}
}
升级版:不仅要求输出最大子列和,还要输出该子列的首末值
// 满分25分只得了22分,有bug还未找到???
import java.util.Scanner;
public class MaxSubSumAndNum {
public static void main(String args[]) {
int maxSum = Integer.MIN_VALUE, thisSum = 0;
int start = 0, end = 0, tmpstart = 0, tmpend = 0;
boolean isNegative = true;
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int[] array = new int[num];
for (int i = 0; i < num; i ++) {
array[i] = in.nextInt();
}
for (int i = 0; i < num; i ++) {
if (array[i] >= 0) isNegative = false;
if (thisSum >= 0) {
thisSum += array[i];
tmpend = i;
} else {
thisSum = array[i];
tmpstart = tmpend = i;
}
if (thisSum > maxSum && isNegative == false) {
maxSum = thisSum;
end = tmpend;
start = tmpstart;
}
}
if (isNegative == true)
System.out.println(0 + " " + array[0] + " " + array[num - 1]);
else
System.out.println(maxSum + " " + array[start] + " " + array[end]);
}
}