最大子序列和的求解问题
1.时间复杂度为o(n3)
思想:三层嵌套循环
最外层i 表示起始下标
中间层j 表示终止下标
最内层 从i到j开始计算序列的和
public static int maxSubSum1(int[] a) {
// 储存最大值
int maxSum=0;
// 外层循环 子序列的起始下标
for(int i=0;i<a.length;i++) {
// 内层循环 子序列的终止下标
for(int j=i;j<a.length;j++) {
// 本次循环的和
int thisSum=0;
// 开始计算子序列的和
for(int k=i;k<=j;k++) {
thisSum+=a[k];
}
// 进行比较
if(thisSum>maxSum) {
maxSum=thisSum;
}
}
}
return maxSum;
}
2.时间复杂度o(n2)
两层嵌套循环
外层 i 表示起始下标
内层 从i开始到最后计算子序列的最大值
public static int maxSubSum2(int[] a) {
int maxSum=0;
// 外层循环 起始下标
// 每一次外层循环计算以i为起始下标的子序列的最大值
for(int i=0;i<a.length;i++) {
int thisSum=0;
// 从起始下标开始计算到后面的每个的和
for(int j=i;j<a.length;j++) {
thisSum+=a[j];
// 每次求和后,比较
if(thisSum>maxSum) {
maxSum=thisSum;
}
}
}
return maxSum;
}
3.O(NlogN)的分治策略
思想:这个子序列出现的地方只有三个
1.前半部分
2.后半部分
3.包含中间值,横跨前后两部分
什么是分治策略?
把问题分成两个大致相等的子问题。然后递归的对他们求解,这是“分”的部分
“治"阶段就是将两个子问题的解修补到一起并可能再做些少量的附加工作,最后得到整个问题的解。
// 从数组a中找到最大子序列和
public static int maxSumRec(int[] a,int left,int right) {
// 该数组只有一个元素
if(left==right) {
if(a[left]>0) {
return a[left];
}else {
return 0;
}
}
// 取中间值
int center =(right-left)/2+left; //为了变了right、left过大超出int类型的范围
// 递归调用求整个数组的左半边的最大子序列和;
int maxLeftSum=maxSumRec(a, left, center);
int maxRightSum=maxSumRec(a, center+1, right);
// 开始求包含中间值的最大子序列和
int maxLeftBorderSum=0,leftBorderSum=0;
// 左边包含中间值的最大子序列和
for(int i=center;i>=left;i--) {
leftBorderSum+=a[i];
if(leftBorderSum>maxLeftBorderSum) {
maxLeftBorderSum=leftBorderSum;
}
}
// 右边包含中间值的最大子序列和
int maxRightBorderSum=0,rightBorderSum=0;
for(int j=center+1;j<=right;j++) {
rightBorderSum+=a[j];
if(rightBorderSum>maxRightBorderSum) {
maxRightBorderSum=rightBorderSum;
}
}
return Math.max(Math.max(maxLeftSum,maxRightSum), maxLeftBorderSum+maxRightBorderSum);
}
public static int maxSubSum3(int[] a) {
int max=maxSumRec(a, 0, a.length-1);
return max;
}
4.时间复杂度为o(n)
只需要一个循环
从i到a.length 计算子序列的最大值
public static int maxSubSum4(int[] a) {
int maxSum=0,thisSum=0;
// 从i到a.length 计算子序列的最大值
for(int i=0;i<a.length;i++) {
thisSum+=a[i];
if(thisSum>maxSum) {
maxSum=thisSum;
}
}
return maxSum;
}
测试代码
// 主方法
public static void main(String[] args) {
int[] a=new int[10000];
for(int i=0;i<10000;i++) {
a[i]=i;
}
// int a[]= {4,-3,5,-2,-1,2,6,-2};
System.out.println(maxSubSum1(a));
System.out.println(maxSubSum2(a));
System.out.println(maxSubSum3(a));
System.out.println(maxSubSum4(a));
}