C++ 最大子列和

在线处理 O(N)

#define k 10000
int MaxSubseqeSum(int a[],int n);
int main()
{
	int n;
	cin >> n;
	int a[k] = { 0 };
	for (int i = 0; i < n; i++)
		cin >> a[i];
	cout<< MaxSubseqeSum(a, n);
	return 0;
}
int MaxSubseqeSum(int a[], int n)
{
	int maxsum = 0, nowsum = 0;
	for (int i = 0; i < n; i++)
	{
		nowsum += a[i];
		if (nowsum > maxsum)
			maxsum = nowsum;
		if (nowsum < 0)
			nowsum = 0;
	}
	return maxsum;
}

在这里插入图片描述

分而治之 O(NlogN)

  1. 将数列一分为二为左右两个子序列,分别求解左侧、右侧、跨中心分界线的最大子列和,整个数列的最大子列和一定在这三者中;
  2. 对左、右半侧的子列继续一分为二重复上述操作,直到一分为二到子列只有一个元素;
  3. 从中间分解线向左右两边扫描,找出跨界最大子列和
  4. 以上操作均由递归完成
#define k 10000
int DAC(int a[], int Left, int Right);//DAC-Divide And Conquer
int Max_3(int a, int b, int c);
int DAC(int a[], int Left, int Right)
{
	int center;
	/*只有一个元素*/
	if (Left == Right)
		if (a[Left] > 0)
			return a[Left];
		else
			return 0;
	/*分*/
	center = (Left + Right) / 2;//找中心元素
	int LSumMax, RSumMax;    //存放左右子问题的解
	LSumMax=DAC(a, Left, center);//递归求左半边
	RSumMax=DAC(a, center + 1, Right);//递归求右半边
	/*求解跨分解线子列*/
	int LSideSumMax = 0, RSideSumMax = 0;  //左(右)侧最大子列和
	int LSideSum=0, RSideSum=0;
	//扫描左边
	for (int i = center; i >= Left; i--)
	{
		LSideSum += a[i];
		DAC(a, Left, center);
		if (LSideSum > LSideSumMax)
			LSideSumMax = LSideSum;
	}
	//扫描右边
	for (int i = center + 1; i < Right; i++)
	{
		RSideSum += a[i]; 
		DAC(a, center + 1, Right);
		if (RSideSum > RSideSumMax)
			RSideSumMax = RSideSum;
	}
	/*返回治的结果*/
	return Max_3(LSumMax, RSumMax, RSideSumMax + LSideSumMax);
}
int main()
{
	int n;
	cin >> n;
	int list[k] = { 0 };
	for (int i = 0; i < n; i++)
		cin >> list[i];
	int R = n - 1;//数组最后元素下标
	cout << MaxSubsequeSum(list, R);
	return 0;
}
int Max_3(int a, int b, int c)
{
	if (a < b) a = b;
	if (a < c) a = c;
	return a;
}
int MaxSubsequeSum(int a[], int n)//用于保证接口相同
{
	return DAC(a, 0, n - 1);
}

三重循环O(N³)

#include "head.h"
#define MAX 10000
int SubseqeMax(int a[], int n);
int SubseqeMax(int a[], int n)
{
	int summax = 0;
	int sum = 0;
	for (int i = 0; i < n; i++) //标记子列左端
	{
		for (int j = i; j < n; j++) //标记子列右端
		{
			sum = 0;//每次求和前清除
			for (int k = i; k < j; k++)//求和
			{
				sum += a[k];
				if (sum > summax)
					summax = sum;
			}
		}
	}
	return summax;
}
int main()
{
	int n;
	cin >> n;
	int a[MAX] = { 0 };
	for (int i = 0; i < n; i++)
		cin >> a[i];
	cout << SubseqeMax(a, n);
	return 0;
}

二重循环 T(O)=(N²)

#define MAX 10000
int SubseqeMax(int a[], int n);
int SubseqeMax(int a[], int n)
{
	int summax = 0;
	int sum = 0;
	for (int i = 0; i < n; i++) //i是子列左端位置
	{
		sum = 0;    //A[i]~A[j]的子列和
		for (int j = i; j < n; j++) //j是子列右端位置
		{
			sum += a[j];    //对于相同的i,不同的j,只要在j-1处再累加1项即可
			if (sum > summax)
				summax = sum;
		}
	}
	return summax;
}
int main()
{
	int n;
	cin >> n;
	int a[MAX] = { 0 };
	for (int i = 0; i < n; i++)
		cin >> a[i];
	cout << SubseqeMax(a, n);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值