算法1
package zui_da_zi_xu_lie_de_he;
/**
* @author hpc
* @Date:2018-7-27下午6:10:57
* 功能:求解最大子序列列的和,若序列中全为负数则和为0;
* 该算法使用穷举法,通过两个for循环列举所有的子序列,再在每一个
* 子序列中使用for循环求和。复杂度:O(n^3)
*/
public class AlgorithmicDemo1 {
public static void main(String[] args) {
int [] a = {1,3,-5,2,1,2,6,-3};
System.out.println(maxSubSum1(a));
}
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
package zui_da_zi_xu_lie_de_he;
/**
* @author hpc
* @Date:2018-7-27下午7:05:30
* 功能:求解最大子序列列的和,若序列中全为负数则和为0;
* 该方法也是使用穷举法,只不过撤除了每举出一个子
* 序列都要重新运算一次和的for循环,改为在上次运算
* 的结果上累加。复杂度:O(n^2)
*/
public class AlgorithmicDemo2 {
public static void main(String[] args) {
int [] a = {1,3,-5,7,1,2,6,-3};
System.out.println(maxSubSum2(a));
}
public static int maxSubSum2(int [] a){
int maxsum = 0;
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
package zui_da_zi_xu_lie_de_he;
/**
* @author hpc
* @Date:2018-7-27下午7:17:49
* 功能:求解最大子序列列的和,若序列中全为负数则和为0;
* 该方法使用分治法,复杂度:O(nlogn)
*/
public class AlgorithmicDemo3 {
public static void main(String[] args) {
int [] a = {1,3,-5,7,-1,2,6,-3};
System.out.println(maxSubSum3(a));
}
public static int maxSumRec(int [] a,int left,int right){//找出以left为起点,以right为终点的数组a的最大子序列的和
if(left == right){
if(a[left]>=0)
return a[left];
else
return 0;
}
int center = (left+right)/2;//找出数组的分界点,把数组分成两半
int maxleftsum = maxSumRec(a,left,center);//找出左一半最大子序列的和
int maxrightsum = maxSumRec(a,center+1,right);//找出右一半最大子序列的和
/*
* 把a数组序列分为两半后,产生和最大的子序列可能在左边,可能在右边,也可能两边都跨越了
* 所以还要找出跨越的最大值,而找出跨越的最大值也是分两部分找,也就是找出左边部分的最大值和
* 右边部分的最大值,再求和就得出跨越部分的最大值。但找的时候要从中间开始找,即左边部分从
* center开始往回找,右边部分从center+1往后找。
*/
int maxleftbordersum = 0;
int leftbordersum = 0;
for(int i = center;i>=left;i--){
leftbordersum+=a[i];
if(leftbordersum>maxleftbordersum)maxleftbordersum=leftbordersum;
}
int maxrightbordersum = 0;
int rightbordersum = 0;
for(int i = center+1;i<=right;i++){
rightbordersum+=a[i];
if(rightbordersum>maxrightbordersum)maxrightbordersum=rightbordersum;
}
return max(maxleftsum,maxrightsum,maxleftbordersum+maxrightbordersum);
}
//找出x,y,z的最大者
public static int max(int x,int y,int z){
int max = 0;
return max = z>(y>x?y:x)?z:(y>x?y:x);
}
public static int maxSubSum3(int [] a){
return maxSumRec(a,0,a.length-1);
}
}
算法4
package zui_da_zi_xu_lie_de_he;
/**
* @author hpc
* @Date:2018-7-27下午8:29:13
* 功能:求解最大子序列列的和,若序列中全为负数则和为0;
* 该算法复杂度:O(n)
*/
public class AlgorithmicDemo4 {
public static void main(String[] args) {
int [] a = {1,3,-5,7,1,2,6,-3};
System.out.println(maxSubSum4(a));
}
public static int maxSubSum4(int [] a){
int maxsum = 0;
int thissum = 0;
for(int i = 0;i<a.length;i++){
thissum+=a[i];
/*
* 使用了一个for循环,大大降低了复杂度。
* 这个算法很巧妙。既然是找最大子序列的和,
* 只要是互相加的因子是正数就符合条件,因为
* 若加了一个负数两者之和必然减少了,而互相
* 加的因子也不一定单纯的指一个数,也可能是
* 某一个子序列的和,所以首先保证序列的起点是正数,
* 往序列中每添加一个数更改thissum,添加完后先与
* maxsum比较,若大则更改maxsum,若小则再与0比较,若比0
* 还小则thissum清0,这表明前面的序列不可能使构成的序列和最大
*/
if(thissum>maxsum)maxsum=thissum;
else if(thissum<0)thissum = 0;
}
return maxsum;
}
}