最大子序列和的求解

算法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;
	}
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值