最大子数组问题

最大子数组问题

定义

Max Continuous Subarray ,MCS

输入

给定一个数组X[1…n],对于任意一对数组下标为l,r(l<=r)的非空子数组,其和记为S(l,r)

输出

求出S(l,r)的最大值,记为Smax

解决方案一: 蛮力枚举

输入数组X[1…n]

伪代码:

int Smax=0;
for (l=1;l<=n;l++)
{
    for(int r=l;l<=n;r++)
    {
        S(l,r)=0;
        for(i=l;i<=r;i++)
        {
            S(l,r)+=X[i];
        }
        Smax=max{Smax,S(l,r)};
    }
}
return Smax;
    

时间复杂度: O(n^3)

解决方案二: 优化枚举法

Smax=0;
for(l=1;l,=n;l++)
{
    S=0;
    for(r=l;r<=n;r++)
    {
        S+=X[r];
        Smax=max{Smax,S};
	}
}
return Smax;

时间复杂度 : O(n^2)

解决方案三: 分为治之

将数组X[1…n]分为X[1…n/2] 和 X[n/2+1…n]

递归求解子问题

S1: 数组X[1…n/2]的最大子数组

S2: 数组X[n/2+1…n]的最大子数组

合并子问题,得到Smax

S3: 跨中点的最大子数组

数组X的最大子数组之和Smax=max{S1,S2,S3}

输入:数组X,数组下标low,high

输出: 最大子数组之和Smax

if(low==high)
    return X[low];
else
{
    int mid = (low+high)/2;
    S1=MaxSubArray(X,low,mid);
    S2=MaxSubArray(mid+1,high);
    S3=CrossingSubArray(X,low,mid,high);
    Smax=max{S1,S2,S3};
    return Smax;
}

时间复杂度 : O(n logn)

解决方案四: 动态规划

Di: 以X[i]开头的最大子数组和

Si: 以X[i]开头的任一子数和

初始化:

D[n]=X[n]

递推公式:

D[i+1]>0 D[i]=X[i]+D[i+1]

D[i=1]<0 D[i]=X[i]

构造追踪数组Rec[1…n]

结尾相同:Rec[i]=i

在这里插入图片描述

输入:数组X,数组长度n

输出: 最大子数组和Smax,子数组起始位置l,r

新建一维数组D[1…n] ,Rec[1…n]

//初始化
int D[n],Rec[n]
D[n] =X[n];
Rec[n]=n;
//动态规划
for (i=n-1;i<=1;i--)
{
    if(D[i+1]>0)
    {
        D[i]=X[i]+D[i+1];
        Rec[i]=Rec[i+1];
    }
    else
    {
        D[i]=X[i];
        Rec[i]=i;
    }
}
//查找解
Smax =D[1];
for (i=2;i<=n;i++)
{
	if(Smax<D[i])
    {
        Smax=D(i);
        l=i;
        r=Rec[i];
    }
}
return Smax,l,r;  

时间复杂度: O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值