现在的位置: 首页 > 综合 > 正文

【第一周】最大子列和问题整理

2017年10月16日 ⁄ 综合 ⁄ 共 1735字 ⁄ 字号 评论关闭

题目地址:01-1. 最大子列和问题

算法一:暴力,直接计算出所有子列和,然后比较,显然复杂度炸裂,O(N^3)

int MaxSubseqSum1(int A[],int N)
{
	int ThisSum;
	int MaxSum = 0;
	int i,j,k;
	for (i = 0; i < N; ++i)//i是子列左端的位置
	{
		for (j = i; j < N; ++j)//j是子列右端的位置
		{
			ThisSum = 0;//A[i]到A[j]的子列和
			for (k = i; k < j ; ++k)
			{
				ThisSum += A[k];
				if (ThisSum > MaxSum)
				{
					MaxSum = ThisSum;
				}
			}
		}
	}
	return MaxSum;
}

算法二:优化第三层循环,将复杂度降到O(N^2)

int MaxSubseqSum2(int A[],int N)
{
	int ThisSum;
	int MaxSum = 0;
	int i,j;
	for (i = 0; i < N; ++i)//i是子列左端的位置
	{
		ThisSum = 0;//A[i]到A[j]的子列和
		for (j = i; j < N; ++j)//j是子列右端的位置
		{	
			ThisSum += A[j];//对于相同的i,不同的j,只要在j-1的基础上累加上1项即可
			if (ThisSum > MaxSum)
			{
				MaxSum = ThisSum;
			}

		}
	}
	return MaxSum;
}

算法三:分而治之,把数组从中间分成两部分,然后递归地解决左右两边,最后考虑跨越边界的最大值。

复杂度的推算:

int MaxSubseqSum3(int A[],int x,int y)
{
	if (y-x==1)
	{
		return A[x];
	}
	int mid = x+(y-x)/2;
	int leftSum = 0;
	int rightSum = 0;
	int leftMaxValue = A[m-1];
	int rightMaxValue = A[m];
	int i;
	int maxValue=max(MaxSubseqSum3(a,x,m),MaxSubseqSum3(a,m,y));
	for (i = mid - 1; i >= x; --i)
	{
		leftSum += A[i];
		leftMaxValue = max(leftMaxValue,leftSum);
	}
	for (i = m; i < y; ++i)
	{
		rightSum += A[i];
		rightMaxValue = max(rightMaxValue,rightSum);
	}
	return max(maxValue,leftMaxValue+rightMaxValue);

}

算法四:在线处理,达到理想的复杂度了,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;
}

=============================================

最后AC的代码:

#include <cstdio>

using namespace std;

#define MAXN 100000
int main()
{
	freopen("in.txt","r",stdin);
	int list[MAXN];
	int n,i,;

	int ThisSum, MaxSum;
	int head,tail;


	scanf("%d",&n);
    int start = 0,end = n-1;
    
	for (int i = 0; i < n; ++i)
	{
		scanf("%d",&list[i]);
	}	
        ThisSum = MaxSum = 0;
        for (int i = 0; i < n; ++i)
        {
    	    if (ThisSum >=0)
    	    {
    		   ThisSum += list[i];
    		   tail = i;
               
    	   }else
    	   {
    		ThisSum = list[i];
    		head = i;
    		tail = i;
    	    }
    	    if (ThisSum > MaxSum ||(ThisSum == 0 && MaxSum == 0))
    	    {
    	    	MaxSum = ThisSum;
    	    	start = head;
    	    	end = tail;
    	    }
         }
           printf("%d %d %d\n",MaxSum, list[start], list[end]);
	return 0;
}

抱歉!评论已关闭.