public class MaxSum {
public static int Sum(int[] array, int n) {
if (array == null || array.length == 0)
return 0;
else {
int MaxSum = 0;
for (int i = 0; i < n; i++) {
//先定开始的下标
for (int j = 0; j < n; j++) {
//后定结束的下标
int Sum = 0;//注意这里令Sum=0,在第二个for之后,想想为什么?因为改变结束的元素下标后,从头开始找子段,此时令Sum=0
for (int k = i; k <= j; k++) {
//在开始的下标与结束的下标之间移动k,从前往后找子段和
Sum = Sum + array[k];//array[K]叠加,后面的array[k]加到原来的Sum里
if (Sum > MaxSum)
MaxSum = Sum;
}
}
}
return MaxSum;
}
}
public static void main(String[] args) {
int[] a = {
4, -3, 5, -2, -1, 2, 6, -2};
int n = a.length;
int result = Sum(a, n);
System.out.println("最大字段和 = "+result);
}
}
比较容易想到,又蠢又笨的方法(看了方法2的分治法就知道为什么又蠢又笨了),用了3个for循环,时间复杂度为O(n^3)。
a = {4, -3, 5, -2, -1, 2, 6, -2}
相对于方法1,就是把方法1的第三个for的if放在第二for里,不要第三个for,用第二个for改变结束下标的同时进行k寻找。时间复杂度为O(n^2)。
public class MaxSum1 {
public static int Max(int[] array, int n) {
if(array.length==0||array==null)
return 0;
else {
int MaxSum = 0;
for (int i = 0; i < n; i++) {
int Sum = 0;
for (int j = i; j < n; j++) {
//改变结束下标的同时(j=i),进行寻找字段和(j++)。
Sum = Sum + array[j];
if (Sum > MaxSum) {
MaxSum = Sum;
}
}
}
return MaxSum;
}
}
public static void main(String[] args) {
int[] a = {
-2,11,-4,13,-5,-2};
int n = a.length;
int result = Max(a, n);
System.out.println("最大子段和 = "+result);
}
}
从中间划分两个区域,在这两个区域内分别用方法1的第三个for。其实就是“二分法”+方法1/2的改进法。时间复杂度为O(nlogn)。(有种换汤不换药的感觉,只是加了二分法)
public class MaxSum2 {
public static int Max(int[] array, int left, int right) {
if (array == null || array.length == 0)
return 0;
int center = (left + right) / 2;
int Sum1 = 0;
int Sum_left = 0;
for (int i = center; i >= left; i--) {
//左半部分最大子段和
Sum1 = Sum1 + array[i];
if (Sum_left < Sum1) {
Sum_left = Sum1;
}
}
int Sum2 = 0;
int Sum_right = 0;
for (int j = center + 1; j <= right; j++) {
//右半部分子段和
Sum2 = Sum2 + array[j];
if (Sum_right < Sum2) {
Sum_right = Sum2;
}
}
int Sum = Sum_left + Sum_right;//左右相加的子段和
if (Sum < Sum_left)
Sum = Sum_left;
if (Sum < Sum_right)
Sum = Sum_right;
return Sum;//左、右、左+右 三部分子段和比较,取最大者
}
public static void main(String[] args) {
int[] a = {
6, -1, 5, 4, -7};
int left = 0;
int right = a.length - 1;
int Max = Max(a, left, right);
System.out.println("最大子段和 = " + Max);
}
}
动态规划递归式:b [ j ] = max { b [ j-1 ] + a [ j ], a [ j ] }
时间复杂度为O(n)
public class MaxSum3 {
public static int Max(int array[], int n) {
int Sum = 0;
int b = 0;//b是个打工仔,从头求到尾,求子段和。
for (int i = 0; i < n; i++) {
if (b > 0)
b = b + array[i];
else
b = array[i];
if (b > Sum)//用Sum来记录前面已经求出来的最大字段和,这样就不必重复计算。
Sum = b;
}
return Sum;
}
public static void main(String[] args) {
int[] a = {
-2,11,-4,13,-5,-2};
int n = a.length - 1;
int result = Max(a, n);
System.out.println("最大子段和 = " + result);
}
}