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

最大连续子段和

2013年05月09日 ⁄ 综合 ⁄ 共 1095字 ⁄ 字号 评论关闭

RT,求一数组中元素的最大连续子段和。

方法一。

  不考虑超时的影响,可以使用循环暴力解决,a[i][j]表示i是开头元素,j为结尾元素,需要使用三层循环,时间复杂度为0(n^3);

 

#include<iostream>
using namespace std;
int b[100][100];
int main()
{
    int a[100];
    int n,k;
    cin>>n;
    for(k=0;k<n;++k)
    cin>>a[k];
    int i,j;
    for(i=0;i<n;++i)
    for(j=i;j<n;++j)
    for(k=i;k<=j;++k)
    {
      b[i][j]=b[i][j]+a[k];
    }
    int max=-222;
    for(int s=0;s<n;++s)
    for(int B=0;B<n;++B)
    if(b[s][B]>max)
    max=b[s][B];
    cout<<max<<endl;
    system("pause");
    return 0;
} 
        
    

方法二。

  方法一中的a[i][j],可以由Sum[j]-Sum[i-1]到,到使时间复杂度降为O(n^2),代码略~

方法三。时间复杂度O(n).

  利用动态规划,由于我是看别人才理解此算法的,所以说说我的理解吧。

#include<iostream>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
      int n,a[100001];
      memset(a,0,100001);
      cin>>n;
      for(int i=0;i<n;++i)
      cin>>a[i];
      int temp=0,max=-32222,k=1;
      for(int j=0;j<n;++j)
      {
      temp=temp+a[j];                    //子段之间的相加
      if(temp>max)
      {
      max=temp;                              //保存最大值的信息
      }
      if(temp<0)                         //舍弃之前的子段
      {
                temp=0;
      }
      }
      cout<<max<<endl;
    }
    system("pause");
    return 0;
}

举个例子,a[4]={-11,-8,9,2}; 显然最大子段和是 9+2=11;

该代码从头到尾扫描一次,如果只有一项,则最大子段和是它本身,不管是否为负数还是正数。

假设第二项为正数的话,显然最大子段和就是第二项本身了,该怎样解决了呢,这样想,因为这是求连续子段和,倘若该项的前n-1项连续子段和为负数,则最大子段和max就会改变,因为一个数加上一个负数,值会减小。所以当前n-1项连续子段和为负数时,就舍弃这一段,从头开始。但注意,最大连续子段和中的元素可以允许有负数的存在,此时就需要设置一个max来保存最大值的情况,如果增加,则更新max的情况,否则不更新。


 

抱歉!评论已关闭.