922-求一个数组的连续子数组的最大和

这篇博客介绍了三种不同的方法来找到数组中所有子数组的最大和。第一种是暴力遍历法,时间复杂度为O(n^2);第二种是动态规划,时间复杂度为O(n);第三种是非动态规划但避免了负数累积,同样为O(n)的时间复杂度。每种方法都通过示例代码进行了详细解释。
摘要由CSDN通过智能技术生成

问题描述

给定一个数组a,数组中的元素有正数也有负数,数组中的一个或连续多个数组成一个子数组。求这些所有子数组的最大和。
例如:a={-1, 2, 3, -4, 5},它的最大和应该是:2+3+(-4)+5=6。

暴力遍历法

从i=0开始到i=length-1,开始往后加,遍历所有的子数组,然后比较每一个子数组的和。
时间复杂度O(n^2),空间复杂度O(1)。代码如下:

#include <iostream>

using namespace std;

int calMaxSumOfArray(int arr[],int n)
{
    if (n == 0)
    {
        return 0;
    }
    if (n == 1)
    {
        return arr[0];
    }
    int sum = arr[0];//初始化sum
    int tmp;
    for (int i = 0; i < n - 1; i++) 
    {
        tmp = arr[i];
        if (sum < tmp)
        {    //这里需要判断一下该数是否比sum大,因为有可能这个数是整个数组的最大子序列和
            sum = tmp;
        }
        //开始从arr[i]往它之后遍历,相加,再跟sum对比
        for (int j = i + 1; j < n; j++) 
        {
            tmp = tmp + arr[j];
            if (sum < tmp) 
            {
                sum = tmp;
            }
        }
    }
    return sum;
}

int main()
{
    int arr[] = { -1, 2, 3, -4, 5 };
    int n = sizeof arr / sizeof(arr[0]);
    cout << calMaxSumOfArray(arr, n) << endl;

    return 0;
}

在这里插入图片描述

动态规划

状态方程:max(dp[i]) = getMax(max(dp[i-1]) + arr[i], arr[i])。

我们从头开始遍历数组,遍历到arr[i]时,最大和可能是dp[i-1])+arr[i],也可能是arr[i]。时间复杂度O(n),空间复杂度O(n)。代码如下:

#include <iostream>

using namespace std;

int max(int a, int b)
{
    return a > b ? a : b;
}

int calMaxSumOfArray(int arr[],int n) 
{
    if (n == 0)
    {
        return 0;
    }
    if (n == 1)
    {
        return arr[0];
    }
    int sum = arr[0];
    int tmp = arr[0];
    for (int i = 1; i < n; i++) 
    {
        tmp = max(tmp + arr[i], arr[i]);
        if (sum < tmp) 
        {
            sum = tmp;
        }
    }
    return sum;
}



int main()
{
    int arr[] = { -1, 2, 3, -4, 5 };
    int n = sizeof arr / sizeof(arr[0]);
    cout << calMaxSumOfArray(arr, n) << endl;

    return 0;
}

在这里插入图片描述

非动态规划的方法

我们从头开始累加,初始sum=arr[0],临时变量tmp=arr[0]。从i=1开始,tep = tep+arr[i],如果tmp小于0,并且发现前面加过的数小于sum,那么舍弃前面的累加值,从i+1开始。代码如下:

#include <iostream>

using namespace std;

int calMaxSumOfArray(int arr[],int n)
{
    if (n == 0)
    {
        return 0;
    }
    if (n == 1) 
    {
        return arr[0];
    }
    int sum = arr[0];
    int tmp = arr[0];
    for (int i = 1; i < n; i++)
    {
        if (tmp < 0) 
        {
            tmp = 0;
        }
        tmp = tmp + arr[i];
        if (sum < tmp) 
        {
            sum = tmp;
        }
    }
    return sum;
}


int main()
{
    int arr[] = { -1, 2, 3, -4, 5 };
    int n = sizeof arr / sizeof(arr[0]);
    cout << calMaxSumOfArray(arr, n) << endl;

    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值