问题描述:
给定长度为n的整数序列,a[1...n], 求[1,n]某个子区间[i , j]使得a[i]+…+a[j]和最大,或者求出最大的这个和。
例如(-2,11,-4,13,-5,2)的最大子段和为20,所求子区间为[2,4]。
1.穷举法
枚举左右区间然后遍历该区间求解,时间复杂度O(n3)
public class Largestsubsection {
public static int FindMax(int []a){
int max = 0;
for(int i = 0;i < a.length;++i){
for(int j = 1;j < a.length;++j){
int sum = 0;
for(int k = i;k <= j;++k){
sum += a[k];
}
if(sum >= max){
max = sum;
}
}
}
return max;
}
public static void main(String[] args) {
int []a = {-2,11,-4,13,-5,2};
int max = FindMax(a);
System.out.println(max);
}
}
2.穷举法+前缀和
在第一种方法的基础上,预处理出前缀和,在枚举左右区间之后,可以通过前缀和直接求解
例如求[l, r]区间的和,直接用sum[r] - sum[l - 1]求出。时间复杂度O(n2)(前缀和sum[i]表示前i位之和)
3.分治法
求解时分治,[1, n]的最大子段和只可能出现在[1, n / 2]或者[n / 2 + 1, n]或者起点位于[1, n / 2],后者位于[n / 2 + 1, n]。就可以直接分治最大子段和。时间复杂度O(nlog(n))。
public class Largestsubsection {
public static int FindMax(int []a,int left,int right){
if(left == right){
return a[left]; //只有一个元素,直接返回
}
int center = (left + right)/2;
// center为0直接返回
if(center == 0){
return 0;
}
//递归求解左右区间的最大值
int max = Math.max(FindMax(a, left, center), FindMax(a, center + 1, right));
int j = 0,L = a[center-1],R = a[center];
for(int i = center - 1;i >= left;--i){
L = Math.max(L, j+=a[i]); // 左区域的最大字段和
}
j = 0; //清空之前的j
for(int i = center;i <= right;++i){
R = Math.max(R, j+=a[i]); // 右区域的最大字段和
}
return Math.max(max, L+R); //合并求解
}
public static void main(String[] args) {
int []a = {-2,11,-4,13,-5,2};
int left = 0,right = a.length-1;
int max = FindMax(a, left, right);
System.out.println(max);
}
}
4.动态规划法
子问题界定:
设前边界为1,后边界为i,且C(i)是子序列A[1,..i]必须包含元素A[i]的向前连续延伸的最大子段和:
递推方程满足:
遍历所有以i (1≤i≤n)为后边界的最大子段和C(i)得出最优解:OPT(A)=max1≤i≤n{Ci}
// 算法复杂度为O(n)
public class Largestsubsection {
public static int FindMax(int []a){
int Sum = 0,Max = 0;
for(int i = 0;i < a.length;++i){ // 子问题后边界
Sum = (Sum + a[i]) > a[i] ? (Sum + a[i]):a[i];
if(Sum > Max){ // 更新最大和
Max = Sum;
}
}
return Max;
}
public static void main(String[] args) {
int []a = {-2,11,-4,13,-5,2};
int max = FindMax(a);
System.out.println(max);
}
}
动态规划算法设计要点:
(1) (划分)多阶段决策过程,每步处理一个子问题,界定子问题的边界(初值问题)。
(2) 列出优化函数的递推方程及初值。
(3) 问题要满足优化原则或者最优子结构性质。即:一个最优决策序列的任何子序列本身一定是相对于子序列的初始和结束状态的最优决策序列。