最大子段和问题

最大子段和问题

给定n个整数(可能为负整数)组成的序列,
求该序列的子段和的最大值。
当所有整数均为负整数时定义其最大子段和为0(相当于取空子段)。

例如:求矩阵序列a[]={-2,1,-4,13,-5,-2}的最大子段和。
结果应为20。

这篇博客主要用于本人之后的复习,如果能帮到读者那最好。

最大子段和问题的简单算法——O(n^2)

int MaxSum(int n, int *a, int &besti, int &bestj) //双重循环求解
{
    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        int thissum = 0;
        for (int j = i; j < n; j++)
        {
            thissum += a[j];
            if (thissum > sum) //找到了更大的子段和
            {
                sum = thissum;
                besti = i;
                bestj = j;
            }
        }
    }
    return sum;
}

最大子段和问题的分治算法——O(nlogn)

int MaxSubSum(int *a, int left, int right) //分治法算法
{
    int sum = 0;
    if (left == right)                   //递归的最里层
        sum = a[left] > 0 ? a[left] : 0; //如果最小单元为负数,那最大子段和为空子段,为0
    else
    {
        int mid = (left + right) / 2;
        int leftsum = MaxSubSum(a, left, mid);       //左子段的最大子段和
        int rightsum = MaxSubSum(a, mid + 1, right); //右子段的最大子段和
        int sum1 = 0, lefts = 0;
        for (int i = mid; i >= left; i--) //这里从右到左是为了从mid向左向右延伸,获取中间的子段和大小
        {
            lefts += a[i];
            if (lefts > sum1)
                sum1 = lefts;
        }
        int sum2 = 0, rights = 0;
        for (int i = mid + 1; i <= right; i++)
        {
            rights += a[i];
            if (rights > sum2)
                sum2 = rights;
        }
        sum = sum1 + sum2; //左右最大子段和相加
        if (sum < leftsum)
            sum = leftsum;
        if (sum < rightsum)
            sum = rightsum; //三者比较取最大值作为该段的最大子段和sum
    }
    return sum;
}

最大子段和问题的动态规划算法——O(n)

int MaxSum2(int n, int *a) //动态规划算法
{
    int sum = 0, temp = 0;
    for (int i = 0; i < n; i++)
    {
        if (temp > 0)
            temp += a[i];
        else
            temp = a[i];
        if (temp > sum)
            sum = temp;
    }
    return sum;
}

在这个问题中,动态规划算法的时间复杂度相对最低。
最后放上main函数部分。

int main()
{
    int a[] = {-2, 11, -4, 13, -5, -2};
    int besti = 0, bestj = 0;
    cout << "sum= " << MaxSum(6, a, besti, bestj) << endl;
    cout << besti << " " << bestj << endl;
    cout << "sum= " << MaxSubSum(a, 0, 5) << endl;
    cout << "sum= " << MaxSum2(6, a) << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值