您的位置:首页 > 其它

最大子序列求和

2014-10-31 15:06 197 查看
问题:给定整数A1,A2,....  (可能有负数),求最大的连续子序列

第一种方法:

暴力求解

int Sum1(const int a[],int n)
{
int maxSum = a[0];
for(int i = 0;i < n ;i++)
for(int j = i;j < n;j++)
{
int temSum = 0;
for(int k = i;k <= j;k++)
temSum += a[k];
if(temSum > maxSum)maxSum = temSum;
}
return maxSum;
}

第二种
暴力求解略微改进

int Sum2(const int a[], int n)
{
int maxSum = a[0];
for(int i = 0;i < n;i++)
{
int tem = 0;
for(int j = i;j < n;j++)
{
tem += a[j];
if(tem > maxSum)maxSum = tem;
}
}
return maxSum;
}


第三种 
分治方法

int Sum3Tem(const int a[],int left,int right)
{
int MaxLeftSum,MaxRightSum;
int MaxLeftBorderSum,MaxRightBorderSum;
int LeftBorder,rightBorder;
int center;

if(left == right)
{
if(a[left])return a[left];
else return 0;
}

center = (left + right) / 2;
MaxLeftSum = Sum3Tem(a,left,center);
MaxRightSum = Sum3Tem(a,center + 1,right);

LeftBorder = 0;MaxLeftBorderSum = 0;
for(int i = center; i >= left; i--)
{
LeftBorder += a[i];
if(LeftBorder > MaxLeftBorderSum)MaxLeftBorderSum = LeftBorder;
}

rightBorder = 0;MaxRightBorderSum = 0;
for(int i = center + 1;i <= right;i++)
{
rightBorder += a[i];
if(rightBorder > MaxRightBorderSum)MaxRightBorderSum = rightBorder;
}

return max(max(MaxLeftSum,MaxRightSum),MaxRightBorderSum + MaxLeftBorderSum);

}

int Sum3(const int a[],int n)
{
return Sum3Tem(a,0,n-1);
}

第四种
动态规划

状态转移方程

dp[i] = max(dp[i-1] + a[i],a[i]);

可以看这篇文章

int Sum4(const int a[],int n)
{
int MaxSum = a[0];
int SumTem = 0;
for(int i = 0;i < n;i++)
{
SumTem += a[i];
if(SumTem > MaxSum)MaxSum = SumTem;
else if(SumTem < 0)SumTem = 0;
}
return MaxSum;
}
=======================
完整代码 测试数据总共有3000个 还在大了 要等太久 3000个可以看出差别了

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include <fstream>

using namespace std;

// O(n 3)
int Sum1(const int a[],int n)
{
int maxSum = a[0];
for(int i = 0;i < n ;i++)
for(int j = i;j < n;j++)
{
int temSum = 0;
for(int k = i;k <= j;k++)
temSum += a[k];
if(temSum > maxSum)maxSum = temSum;
}
return maxSum;
}
//O (n 2)
int Sum2(const int a[], int n)
{
int maxSum = a[0];
for(int i = 0;i < n;i++)
{
int tem = 0;
for(int j = i;j < n;j++)
{
tem += a[j];
if(tem > maxSum)maxSum = tem;
}
}
return maxSum;
}

int Sum3Tem(const int a[],int left,int right)
{
int MaxLeftSum,MaxRightSum;
int MaxLeftBorderSum,MaxRightBorderSum;
int LeftBorder,rightBorder;
int center;

if(left == right)
{
if(a[left])return a[left];
else return 0;
}

center = (left + right) / 2;
MaxLeftSum = Sum3Tem(a,left,center);
MaxRightSum = Sum3Tem(a,center + 1,right);

LeftBorder = 0;MaxLeftBorderSum = 0;
for(int i = center; i >= left; i--)
{
LeftBorder += a[i];
if(LeftBorder > MaxLeftBorderSum)MaxLeftBorderSum = LeftBorder;
}

rightBorder = 0;MaxRightBorderSum = 0;
for(int i = center + 1;i <= right;i++)
{
rightBorder += a[i];
if(rightBorder > MaxRightBorderSum)MaxRightBorderSum = rightBorder;
}

return max(max(MaxLeftSum,MaxRightSum),MaxRightBorderSum + MaxLeftBorderSum);

}

int Sum3(const int a[],int n)
{
return Sum3Tem(a,0,n-1);
}

int Sum4(const int a[],int n)
{
int MaxSum = a[0];
int SumTem = 0;
for(int i = 0;i < n;i++)
{
SumTem += a[i];
if(SumTem > MaxSum)MaxSum = SumTem;
else if(SumTem < 0)SumTem = 0;
}
return MaxSum;
}

int main()
{

const int num = 3000;
//int a[6] = {-2,11,-4,13,-5,-2};
int b[num];
clock_t start,finish;

freopen("randNum.txt","r",stdin);
for(int i = 0;i < num;i++)
cin>>b[i];

start = clock();
cout<<"sum1: "<<Sum1(b,num);
finish = clock();
cout<<" cost "<<double(finish - start) / CLOCKS_PER_SEC<<endl;

start = clock();
cout<<"sum2: "<<Sum2(b,num);
finish = clock();
cout<<" cost "<<double(finish - start) / CLOCKS_PER_SEC<<endl;

start = clock();
cout<<"sum3: "<<Sum3(b,num);
finish = clock();
cout<<" cost "<<double(finish - start) / CLOCKS_PER_SEC<<endl;

start = clock();
cout<<"sum4: "<<Sum4(b,num);
finish = clock();
cout<<" cost "<<double(finish - start) / CLOCKS_PER_SEC<<endl;

return 0;
}




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

为了得到测试数据

先写了一个随机数生成的程序,随机生成1000个数,范围[-100,100)

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstdio>

using namespace std;

int main()
{

srand(time(NULL));

freopen("randNum.txt","w",stdout);
int totalNum = 1000;
while(totalNum--)
{
cout<<(rand() % 200  - 100)<<" ";
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: