最大子列和问题

问题

给定一个数列,其中可能有正数也可能有负数,我们的任务是找出其中连续的一个子数列(不允许空序列),使它们的和尽可能大。

算法一:时间复杂度O(N^3)

/*算法一*/ 
int MaxSubseqSum1(int A[], int N) {
	int ThisSum, MaxSum = 0;
	int i, j, k;
	for(i = 0; i < N; i++) {            //i是子列左端位置 
		for(j = i; j < N; j++) {		//j是子列右端位置 
			ThisSum = 0;				//ThisSum是从A[i]到A[j]的子列和 
			for(k = i; k <= j; k++) {
				ThisSum += A[k];
			}		
			if(ThisSum > MaxSum) {		//如果刚得到的子列和比MaxSum更大 
				MaxSum = ThisSum;		//则更新结果 
			}	
		}								//j循环结束 
	}									//i循环结束 
	return MaxSum;
} 

算法二:时间复杂度O(N^2)

/*算法二*/ 
int MaxSubseqSum2(int A[], int N) {
	int ThisSum, MaxSum = 0;
	int i, j;
	for(i = 0; i < N; i++) {			//i是子列左端位置 
		ThisSum = 0; 					//ThisSum是从A[i]到A[j]的子列和 
		for(j = i; j < N; j++) {		//j是子列右端位置
			ThisSum += A[j];			//对于相同的i,不同的就,只要在j-1次循环的基础上累加一项即可 
			if(ThisSum > MaxSum) {		//如果刚得到的子列和比MaxSum更大
				MaxSum = ThisSum;		//则更新结果
			}
		}								//j循环结束
	}									//i循环结束
	return MaxSum; 
}

算法三:分治法,时间复杂度O(NlogN)

/*算法三:分治法*/ 

/*返回三个整数的最大值*/ 
int Max3(int A, int B, int C) {								
	return (A > B) ? (A > C ? A : C) : (B > C ? B : C); 
}

/*分治法求List[left]到List[right]的最大子列和*/
int DivideAndConquer(int List[], int left, int right) {
	int MaxLeftSum, MaxRightSum;						//存放左右子问题的解 
	int MaxLeftBorderSum, MaxRightBorderSum;			//存放跨分界线的结果 
	
	int LeftBorderSum, RightBorderSum;
	int center, i;
	
	/*递归的终止条件,子列只有1个数字*/
	if(left == right) {
		if(List[left] > 0) 
		return List[left];
		else
		return 0; 
	} 
	
	 /*“分”的过程 */
	center = (left + right) / 2;			//找到中分点 
	MaxLeftSum = DivideAndConquer(List, left, center);    //递归求左子列和 
	MaxRightSum = DivideAndConquer(List, center + 1, right);  //递归求右子列和 
	
	/*求跨分界线的最大子列和*/
	MaxLeftBorderSum = 0; 
	LeftBorderSum = 0;
	for(i = center; i >= left; i--) {
		LeftBorderSum += List[i];
		if(LeftBorderSum > MaxLeftBorderSum)
		MaxLeftBorderSum = LeftBorderSum; 
	}//左边扫描结束。
	
	MaxRightBorderSum = 0; 
	RightBorderSum = 0; 
	for(i = center + 1; i <= right; i++) {
		RightBorderSum += List[i];
		if(RightBorderSum > MaxRightBorderSum)
		MaxRightBorderSum = RightBorderSum; 
	}//右边扫描结束。
	
	/*返回“治”的结果*/ 
	return Max3(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum);
}

/*此函数用于保持接口相同*/ 
int MaxSubseqSum3(int List[], int N) {
	return DivideAndConquer(List, 0, N-1);
}

算法四:在线处理,时间复杂度O(N)

/*算法四:在线处理*/
int MaxSubseqSum4(int A[], int N) {
	int ThisSum, MaxSum;
	int i;
	ThisSum = MaxSum = 0;
	for(i = 0; i < N; i++) {
		ThisSum += A[i];		//向右累加 
		if(ThisSum > MaxSum) 
		MaxSum = ThisSum;		//发现更大和则更新当前结果 
		else if(ThisSum < 0)	//如果当前子列和为负 
		ThisSum = 0;			//则不可能使后面的部分和增大,抛弃之 
	} 
	return MaxSum;
} 

最后,写一个主函数进行测试,第1行输入正整数n;第2行给出n个整数,其间以空格分隔。

#include <stdio.h>
#define MAX 100000    
int main() {
	int n, i;
	int a[MAX] = {0};
	scanf("%d", &n);
	for ( i = 0; i < n; i++ )
		scanf("%d", &a[i]);
	printf("%d", MaxSubseqSum1( a, n ));   
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值