最大子序列和问题

输入一组整数,求出这组数字子序列和中最大值。也就是只要求出最大子序列的和,不必求出最大的那个序列。例如:{4,-3,5,-2,6,-7,1}的最大子序列和是10。


算法1,


//穷举法,时间复杂度O(N^3)
int MaxSub(int Data[])
{
   int len = sizeof(Data)/sizeof(int);
   int MaxSum = 0;
   for (int i = 0;i <len;i++)
   {
      for (int j = i;j<len;j++)
      {
         int sum = 0;
         for (int k = i;k<j;k++)
         {
             sum += Data[k];
          }
         if (MaxSum < sum)
         {
             MaxSum = sum;
          }
       }
    }
    return MaxSum;
}

算法2

//穷举法,时间复杂度O(N^2)
int MaxSub(int Data[])
{
    int len = sizeof(Data)/sizeof(int)
    int MaxSum = 0;
                                                                                                                                                                                                 
    for (int i = 0;i<len;i++)
    {
        int sum = 0;
        for (int j = i;j<len;j++)
        {
            sum += Data[j];
         }
         if (sum > MaxSum)
         {
             MaxSum = sum;
          }
      }
     return MaxSum;
}

算法3

采用分治算法思想,时间复杂度O(NlogN);

最大序列只可能出现在序列的左边,右边或者跨越左右两边,用递归的方法可以解决问题。


int Max(int a,int b,int c)
{
    int max = a;
    if (max < b){
        max = b;
    }
    if (max <c){
        max = c;
    }
    return max;
}
int MaxSub(int first,int last,int Data[])
{
    int lSum = 0;
    int rSum = 0;
    int lMaxSum = 0;
    int rMaxSum = 0;
                                                           
    int middle = (first + last)/2;
        
    if (last < first )      
         return 0;
                                                  
    if (last == first)
        return Data[first];
    int lData = MaxSub(first,middle,Data);
    int rData = MaxSub(middle+1,last,Data);
                                                                                 
    lMaxSum = Data[middle];
    for (int i = middle;i>=first;i--)
    {
        lSum += Data[i];
        if (lSum > lMaxSum){
            lMaxSum = lSum;
        }
    }
                                                                                 
    rMaxSum = Data[middle+1];
    for (int j = middle+1;j<=last;j++)
    {
        rSum += Data[j];
    if (rSum >rMaxSum)
    {
        rMaxSum = rSum;
    }
    }
    int num = Max(rData,lData,rMaxSum + lMaxSum);
    return num;
}

算法4

下面介绍一个线性的算法,这个算法是许多聪明算法的典型,时间复杂度为O(N)。

主要思想:如果a[i]是负数那么它不可能代表最大序列的起点,因为任何包含a[i]的作为起点的子序列都可以通过用a[i+1]作为起点来改进。类似的有,任何的负的子序列不可能是最优子序列的前缀。

long maxSubSum4(int a[],int len)
{
    int maxsum, maxhere;
    maxsum = maxhere = a[0];   //初始化最大和为a【0】
    for (int i=1; i<len; i++)
   {
        if (maxhere <= 0)
            maxhere = a[i];  //如果前面位置最大连续子序列和小于等于0,则以当前位置i结尾的最大连续子序列和为a[i]
        else
            maxhere += a[i]; //如果前面位置最大连续子序列和大于0,则以当前位置i结尾的最大连续子序列和为它们两者之和
        if (maxhere > maxsum) {
            maxsum = maxhere;  //更新最大连续子序列和
        }
    }
    return maxsum;
                                                                                    
}

遍历到a[i]时,如果a[i]前面的子序列和小于零,则将maxhere置为a[i],因为负的子序列和不会优化得到最大子序列。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值