vlambda博客
学习文章列表

用动态规划算法求最大子序和

问题描述:

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。


示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。


动态规划解析:

状态定义:设动态规划列表 dp,dp[i]代表以元素 nums[i]为结尾的连续子数组最大和。

为何定义最大和 dp[i]中必须包含元素 nums[i]:保证 dp[i]递推到 dp[i+1]的正确性;如果不包含 nums[i],递推时则不满足题目的连续子数组要求。


转移方程:若dp[i−1]≤0 ,说明 dp[i - 1]对 dp[i]产生负贡献,即 dp[i-1] + nums[i]还不如 nums[i]本身大。


当 dp[i - 1] >0 时:执行 dp[i] = dp[i-1] + nums[i];

当 dp[i - 1] ≤0 时:执行 dp[i]=nums[i] ;


初始状态:dp[0] = nums[0],即以 nums[0]结尾的连续子数组最大和为 nums[0] 。


返回值:返回 dp列表中的最大值,代表全局最大值。



复杂度分析:


时间复杂度 O(N): 线性遍历数组 nums 即可获得结果,使用 O(N) 时间。

空间复杂度 O(1): 使用常数大小的额外空间。


代码:


int maxSubArray(int* nums, int numsSize){

    if (!nums || numsSize <= 0)

    {

        return -0x80000000;

    }


    int dp = nums[0];

    int max = dp;

    int i;

    for (i = 1;i < numsSize;i ++)

    {

        if (dp < 0)

        {

            dp = nums[i];

        }

        else

        {

            dp = dp + nums[i];

        }


        if (max < dp)

        {

            max = dp;

        }

    }


    return max;

}