求数组中的子数组之和的最大值

《编程之美》第2.14节:求数组中的子数组之和的最大值

题目:有一个有N个元素组成的一维数组,这个数组中当然有很多子数组,那么子数组之和的最大值是多少?

解法:从头到尾遍历整个数组,不断加和,如果临时和temp<0了,则清零,否则继续加。

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;

int subarrySum(int *A,int N)//返回要排除的值
{
	int result=INT_MIN;
	int temp=0;
	for(int i=0;i<N;i++)
	{
		temp+=A[i];
		if(temp>result)
			result=temp;
		if(temp<0)
			temp=0;
	}
	return result;
}

int main()
{
	int A[6]={-9,-2,-3,-5,-3,-8};
	cout<<subarrySum(A,6)<<endl;

	system("pause");
	return 0;
}
测试用例:

1,-2,3,5,-3,-2  输出结果:8

 0,-2,3,5,-1,2  输出结果:9

-9,-2,-3,-5,-3,-8 输出结果:-2


题目2:如果数组首尾相邻,使其和最大,怎么办?

解法:只需要在原来的基础上添加从头开始和从尾开始的最大值之和,如果比原来的值大,则返回,如果比原来值小,则返回原来的结果。

代码:

#include<iostream>
#include<algorithm>
using namespace std;

int subarrySum(int *A,int N)//返回要排除的值
{
	int result=INT_MIN;
	int temp=0;
	for(int i=0;i<N;i++)
	{
		temp+=A[i];
		if(temp>result)
			result=temp;
		if(temp<0)
			temp=0;
	}
	temp=0;
	int firstResult=INT_MIN,lastResult=INT_MIN;
	int end=0;
	for(int i=0;i<N;i++)
	{
		temp+=A[i];
		if(temp>firstResult)
		{
			firstResult=temp;
			end=i;
		}
	}
	temp=0;
	for(int i=N-1;i>end;i--)
	{
		temp+=A[i];
		if(temp>lastResult)
			lastResult=temp;
	}

	return max(result,firstResult+lastResult);
}

int main()
{
	int A[6]={1,2,-3,-5,-3,3};
	cout<<subarrySum(A,6)<<endl;

	system("pause");
	return 0;
}

问题三:如果要返回最大子数组的位置,应该如何改变,能否保证O(N)的算法复杂度?

解法:只需要保存最后一个元素的下标,然后再计算一次结果即可,复杂度仍然是O(N)。

代码:

#include<iostream>
#include<algorithm>
using namespace std;

pair<int,int> subarrySum(int *A,int N)//返回要排除的值
{
	int result=INT_MIN;
	int temp=0,index=-1;
	for(int i=0;i<N;i++)
	{
		temp+=A[i];
		if(temp>result)
		{
			result=temp;
			index=i;
		}
		if(temp<0)
			temp=0;
	}
	temp=0;
	int firstResult=INT_MIN,lastResult=INT_MIN;
	int end=0,firstIndex=-1,lastIndex=-1;
	for(int i=0;i<N;i++)
	{
		temp+=A[i];
		if(temp>firstResult)
		{
			firstResult=temp;
			end=i;
			firstIndex=i;
		}
	}
	temp=0;
	for(int i=N-1;i>end;i--)
	{
		temp+=A[i];
		if(temp>lastResult)
		{
			lastResult=temp;
			lastIndex=i;
		}
	}
	if(result<firstResult+lastResult)
		return pair<int,int>(lastIndex,firstIndex);
	else
	{
		temp=0;
		int i=0;
		for(i=index;temp!=result;i--)
		{
			temp+=A[i];
		}
		return pair<int,int>(i,index);
	}
}

int main()
{
	int A[6]={1,2,-3,-5,-3,3};
	pair<int,int>result=subarrySum(A,6);
	cout<<result.first<<"	"<<result.second<<endl;

	system("pause");
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值