问题描述:
给定任意n个整数(可能为负数),组成序列a1,a2,a3,a4,a5,...,an, 求该序列的的子段和的最大值.
输入:
-2,11,-4,13,-5,-2
输出:
20
最大子段为: 11,-4,13 结果为:11-4+13=20
第一种方法,暴力求解:
package spam;
/**
* Created by panther on 17-3-22.
*/
public class MaxSubSegment {
public static void main(String[] args) {
int arr[] = new int[]{-2, 11, -4, 13, -5, -2};
System.out.println(maxSum(arr.length, arr));
}
private static int maxSum(int n, int[] arr) {
int sum = 0;
for (int i = 0; i < n; ++i) {
for (int j = i; j < n; ++j) {
int thissum = 0;
for (int k = i; k < j; ++k) {
thissum += arr[k];
}
if (thissum > sum) {
sum = thissum;
}
}
}
return sum;
}
}
时间复杂度为: O(n^3)
算法优化:
package spam;
/**
* Created by panther on 17-3-22.
*/
public class MaxSubSegment {
public static void main(String[] args) {
int arr[] = new int[]{-2, 11, -4, 13, -5, -2};
System.out.println(maxSum(arr.length, arr));
}
private static int maxSum(int n, int[] arr) {
int sum = 0;
for (int i = 0; i < n; ++i) {
int thissum = 0;
for (int j = i; j < n; ++j) {
// for (int k = i; k < j; ++k) {
thissum += arr[j];
// }
if (thissum > sum) {
sum = thissum;
}
}
}
return sum;
}
}
改进后的算法少了一层循环,避免了求和的 重复计算,时间复杂度为O(n^2)
动态规划算法实现:
记b[j]为从1到j的最大字段和,由定义可知道,当b[j-1]>0时, b[j]=b[j-1]+a[j],否则b[j]=a[j].
由此可以知道b[j]的 动态规划递归公式:
b[j]=max{b[j-1]+a[j],a[j]},1<=j<=n
算法实现
private static int dynamicMaxSum(int n, int[] arr) {
int sum = 0, b = 0;
for (int i = 0; i < n; ++i) {
if (b > 0) {
b += arr[i];
} else {
b = arr[i];
}
if (b > sum) sum = b;
}
return sum;
}
时间复杂度是O(n)