最大的子序列和问题

最大的子序列和问题

问题描述:最大的子序列和问题,给定(有可能负的整数)a1,a2,…,aN,求最大子序列和(为方便起见,如果所有整数均为负数,则最大子序列的和为0)

  1. 第一种算法
    时间复杂度为O(N3)
int maxSubSum1( const vector<int> & a )
{
  int maxSum = 0;

  for(int i = 0; i < a.size(); ++i)
    for(int j = i; j < a.size(); ++j)
    {
       int thisSum = 0;

       for(int k = i; k <= j; ++k)
        thisSum += a[k];

        if(thisSum > maxSum)
        maxSum = thisSum;
    }
    return maxSum;
}

2.第二种算法
时间复杂度O(N2)

int maxSubSum2(const vector<int> & a)
{
  int maxSum = 0;
  for(int i = 0;i < a.size(); ++i)
  {
    int thisSum = 0;
    for(int j = 1;j < a.size(); ++j)
    {
      thisSum += a[j];

      if(thisSum > maxSum)
      maxSum = thisSum;
    }
  }
  return maxSum;
}

3.第三种算法
时间复杂度为O(NlogN)

int maxSumRec(const vector<int> & a,int left, int right)
{
  if(left == right)
    if(a[left] > 0)
      return a[left];
    else
      return 0;
      
  int center = (left + right)/2;
  int maxLeftSum = maxSumRec(a, left, center);
  int maxRightSum = maxSumRec(a, center+1, right);

  int maxLeftBorderSum = 0,leftBorderSum = 0;
  for(int i = center; i >= left; --i)
  {
    leftBorderSum += a[i];
    if(leftBorderSum > maxLeftBorderSum)
    maxLeftBorderSum = leftBorderSum;
  }
  int maxRightBorderSum = 0,rightBorderSum = 0;
  for(int j = center+1; j <= right; ++j)
  {
    rightBorderSum += a[j];
    if(rightBorderSum > maxRightBorderSum)
    maxRightBorderSum = rightBorderSum;
  }

  return (maxLeftSum, maxRightSum,
                  maxLeftBorderSum + maxRightBorderSum);
    
}
int maxSubSum3(const vector<int> & a)
{
  return maxSumRec(a, 0, a.size()-1);
}

4.第四种算法

int maxSubSum4(const vector<int> & a)
{
  int maxSum = 0, thisSum = 0;
  for(int j = 0; j < a.size(); ++j)
  {
    thisSum += a[j];
    if(thisSum > maxSum)
      maxSum = thisSum;
    else 
      if(thisSum < 0)
        thisSum = 0;
  }
  return maxSum;
}

这里是自己测试算法的程序源码

#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<string>


using namespace::std;
//最大的子序列和问题
//给定(有可能负的整数)a1,a2,...,aN,求最大子序列和
//(为方便起见,如果所有整数均为负数,则最大子序列的和为0)


//第一种算法
//遍历全部
//时间复杂度最大
int maxSubSum1( const vector<int> & a )
{
  int maxSum = 0;

  for(int i = 0; i < a.size(); ++i)
    for(int j = i; j < a.size(); ++j)
    {
       int thisSum = 0;

       for(int k = i; k <= j; ++k)
        thisSum += a[k];

        if(thisSum > maxSum)
        maxSum = thisSum;
    }
    return maxSum;
}



//第二种算法
//改进的第一种算法
//但是还不知道为什么 结果有一些问题
int maxSubSum2(const vector<int> & a)
{
  int maxSum = 0;
  for(int i = 0;i < a.size(); ++i)
  {
    int thisSum = 0;
    for(int j = 1;j < a.size(); ++j)
    {
      thisSum += a[j];

      if(thisSum > maxSum)
      maxSum = thisSum;
    }
  }
  return maxSum;
}



//第三种算法
//分为左右分别计算
//利用递归计算 此时假设数组大小是个偶数
int maxSumRec(const vector<int> & a,int left, int right)
{
  if(left == right)
    if(a[left] > 0)
      return a[left];
    else
      return 0;
      
  int center = (left + right)/2;
  int maxLeftSum = maxSumRec(a, left, center);
  int maxRightSum = maxSumRec(a, center+1, right);

  int maxLeftBorderSum = 0,leftBorderSum = 0;
  for(int i = center; i >= left; --i)
  {
    leftBorderSum += a[i];
    if(leftBorderSum > maxLeftBorderSum)
    maxLeftBorderSum = leftBorderSum;
  }
  int maxRightBorderSum = 0,rightBorderSum = 0;
  for(int j = center+1; j <= right; ++j)
  {
    rightBorderSum += a[j];
    if(rightBorderSum > maxRightBorderSum)
    maxRightBorderSum = rightBorderSum;
  }

  return (maxLeftSum, maxRightSum,
                  maxLeftBorderSum + maxRightBorderSum);
    
}
int maxSubSum3(const vector<int> & a)
{
  return maxSumRec(a, 0, a.size()-1);
}



//第四种算法
int maxSubSum4(const vector<int> & a)
{
  int maxSum = 0, thisSum = 0;
  for(int j = 0; j < a.size(); ++j)
  {
    thisSum += a[j];
    if(thisSum > maxSum)
      maxSum = thisSum;
    else 
      if(thisSum < 0)
        thisSum = 0;
  }
  return maxSum;
}





int main()
{
  int abc[10] = {1, 2, 5, -5, 9, -11, 29, 4, 7, 2};
  std::vector<int> vector_abc(abc, abc+10);

  int Sum = maxSubSum4(vector_abc);
  cout<< Sum << endl;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值