最大连续子序列和

题目:

给你一个数组:1,12,-15,13,-2,6,求最大连续子序列和,这个题的答案是17,也就是13,-2,6

方法一(暴力法):
#include<iostream>//暴力法 
#include<cstdio>
#include<algorithm> 
using namespace std;
const int MAXN=1e5;
int arr[MAXN];
int MaxSubArray1(int n)//n3 
{
	int ans=0x80000000;//int最小值
	for(int i=0;i<n;i++)//序头 
	{
		for(int j=i;j<n;j++)//序尾 
		{
			int sum=0;
			for(int k=i;k<=j;k++)//遍历序头到序尾 
			{
				sum+=arr[k];
			}
			ans=max(ans,sum);
		}
	}
	return ans;
}
int MaxSubArray2(int n)//n2 
{
	int ans=0;
	for(int i=0;i<n;i++)//序头 
	{
		int sum=0;
		for(int j=i;j<n;j++)//序尾 
		{
			sum+=arr[j];
			ans=max(ans,sum);
		}
	}
	return ans;
}
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++) 	cin>>arr[i];
	cout<<MaxSubArray2(n)<<endl;
	return 0;
} 

这种方法不建议大家使用,容易超时,竟然我们学了算法,有没有用算法来解决的呢,当然是有的,我们来看一看法二;

方法二(分治法):

分治法也就是进行递归操作,也就是分而治之,将一个大问题分成很多个小问题,挨个挨个解决小问题,最后大问题就得到了解决;回到这个题,我们可以把这个序列分成一半,我们要解决的事,这个最大连续子序列和在这个分界点的两边,或者是中间,若是在两边的话那我们是否可以直接求出呢,如果在中间的话那么就求分界点前面的最大后缀和,和分界点后面的最大前缀和。然后递归一半的一半。。。问题就迎刃而解了。下面来看看代码吧。

#include<iostream>//分治法:从中间到两边,要么全在左边或者右边,要么跨立在中间,跨立在中间的只需要求一个前面的后缀和一个后面的前缀和 
#include<cstdio>//复杂度为nlongn 
#include<algorithm>
using namespace std;
const int MAXN=1e5;
int arr[MAXN];
int MaxAddArray(int from,int to)
{
	if(to==from)	return arr[to];
	int middle=(to+from)>>1;
	int m1=MaxAddArray(from,middle);
	int m2=MaxAddArray(middle+1,to);
	int left=arr[middle],sum=arr[middle];
	for(int i=middle-1;i>=from;i--)//前面的后缀
	{
		sum+=arr[i];
		left=max(left,sum);
	}
	int right=arr[middle+1];
	sum=arr[middle+1];
	for(int i=middle+2;i<=to;i++)//后面的前缀 
	{
		sum+=arr[i];
		right=max(right,sum);
	}
	int m3=left+right;
	return max(max(m1,m2),m3);
}
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++)	cin>>arr[i];
	cout<<MaxAddArray(0,n-1)<<endl;
	return 0;
} 

当然我们这里的时间复杂度为O(nlogn),由于我的数学不好,在此就不证明了。那还有没有效率更高的代码呢,当然是有的。

方法三(分析法):

这里的分析法也就是动态规划,我对动态规划还不是特别熟悉,所以只在这里说一下思路。我们可以用sum存储的是前n项和,假设sum小于0,则不在i到j,在后面,而ans就是当前最大的值。

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=1e5;
int arr[MAXN];
int main()
{
	int n,sum=0,ans=0;
	cin>>n;
	for(int i=0;i<n;i++)	cin>>arr[i];
	for(int i=0;i<n;i++)
	{
		sum+=arr[i];
		ans=max(ans,sum);
		if(sum<0)	sum=0;
	}
	return 0;
}

这个算法就是线性的,所以时间复杂度为O(n);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空皓月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值