一、比较朴素的算法
算法思想:我们确定每个子段和开始的位置,分别为第一个,第二个,第三个......第N个,然后计算从这个位置开始到这个位置之后的每个位置的子段和,更新记录最大的子段和。
时间复杂度:O(n^2)
算法实现(Java):
package com.Third; import java.util.*; public class Main3{ public static int maxSum2(int a[]){ int nowSum=0;//用于记录从指定位置到当前位置累加的值 int maxSum=0;//用于记录当前最大的子段和 for(int i=0;i<a.length;i++){ nowSum=0; for(int j=i;j<a.length;j++){ nowSum=nowSum+a[j]; if(nowSum>maxSum){//更新最大子段和 maxSum=nowSum; } } } return maxSum; } public static void main(String[] args) { int a[]={4,-3,5,-2,-1,2,6,-2}; System.out.println(maxSum2(a)); } }
二、分治法(递归)
算法思想:
通过分治的思想求最大子段和,将数组分平均分为两个部分,则最大子段和会存在于三种情况下:
1.最大子段和出现在左端
2.最大子段和出现在右端
3.最大子段和横跨在左右段 通过比较大小得到最大子段和
时间复杂度:O(nlogn)
算法实现(Java):
package com.Third; /* * 通过分治的思想求最大子段和,将数组分平均分为两个部分,则最大子段和会存在于三种情况下: * 1.最大子段和出现在左端 * 2.最大子段和出现在右端 * 3.最大子段和横跨在左右段 */ public class Main { public static int maxSumRec(int []a,int start,int end){ if(start==end){//这里是递归的函数出口 if(a[start]>0){ return a[start]; }else{ return 0; } } int maxLeftSumRec=maxSumRec(a,start,(start+end)/2);//计算左半边的最大字段和 int maxRightSumRec=maxSumRec(a,((start+end)/2)+1,end);//计算右半边最大子段和 //计算最大子段和在中间的情况 int leftMaxMark=0; int leftSum=0; for(int i=(start+end)/2;i>=0;i--){ leftSum=leftSum+a[i]; if(leftSum>leftMaxMark){ leftMaxMark=leftSum; } } int rightMaxMark=0; int rightSum=0; for(int i=((start+end)/2)+1;i<=end;i++){ rightSum=rightSum+a[i]; if(rightSum>rightMaxMark){ rightMaxMark=rightSum; } } int maxMidSumRec=leftMaxMark+rightMaxMark; //比较三种情况那种情况是最大的子段和 int maxSum=maxLeftSumRec; if(maxSum<maxRightSumRec){ maxSum=maxRightSumRec; } if(maxMidSumRec>maxSum){ maxSum=maxMidSumRec; } return maxSum; } public static void main(String[] args) { int a[]={4,-3,5,-2,-1,2,6,-2}; System.out.println(maxSumRec(a,0,7)); } }
三、动态规划算法
算法思想:
运用了动态规划的思想来解决最大子段和问题:
通过遍历累加这个数组元素,定时的更新最大子段和,
如果当前累加数为负数,直接舍弃,重置为0,然后接着遍历累加。
时间复杂度:O(n)
算法实现(Java):
package com.Third; /* * 这是运用了动态规划的思想来解决最大子段和问题: * 通过遍历累加这个数组元素,定时的更新最大子段和, * 如果当前累加数为负数,直接舍弃,重置为0,然后接着遍历累加。 */ public class Main1{ public static int maxSubSum1(int []a){ int maxSum=0; int nowSum=0; for(int i=0;i<a.length;i++){ nowSum=nowSum+a[i]; if(nowSum>maxSum){//更新最大子段和 maxSum=nowSum; } if(nowSum<0){//当当前累加和为负数时舍弃,重置为0 nowSum=0; } } return maxSum; } public static void main(String[] args) { int a[]={4,-3,5,-2,-1,2,6,-2}; System.out.println(maxSubSum1(a)); } }