LeetCode 53. 最大子序和:

111 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

53. 最大子序和

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

示例:

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

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

链接:https://leetcode-cn.com/problems/maximum-subarray

方法1 暴力法:

思路: (略)

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

空间复杂度: O(1)

// 暴力法:
int maxSubArray(vector<int>& nums) {
    int max = INT_MIN;           // 初始值一定要定义成理论上的最小最大值
    int numsSize = nums.size();  // 不用每次计算长度,效率更高,耗时更少
    for (int i = 0; i < numsSize/*nums.size()*/; i++)
    {
        int sum = 0;
        for (int j = i; j < numsSize/*nums.size()*/; j++)
        {
            sum += nums[j];
            max = max > sum ? max : sum; 
        }
    }
    return max;
}

方法2 动态规划:

思路:

dp[i]表示nums中以nums[i]结尾的最大子序和,dp[i]有两种可能的情况,取较大者:

(1)要么是当前数字numsi

(2)要么是每一轮循环中的前n项和更大(每一轮循环中的前n项和大于当前数nums[i],注意外循环起点不同)

时间复杂度: O(n)

空间复杂度: O(1)  空间复杂度可优化至O(1),因为只需要知道dp的前一项,可以用int代替一维数组

// dp(内存优化版,一位数组代替):
int maxSubArray(vector<int>& nums) {
    int dp = nums[0];                       // 如果输入是[1]的话,则返回nums[0]
    int maxVul = dp;
    for (int i = 1; i < nums.size(); i++)
    {                                       // dp[i]表示nums中以nums[i]结尾的最大子序和
        dp = max(nums[i], nums[i] + dp);    // 因为只需要知道dp的前一项,可以用int代替一维数组
        maxVul = max(maxVul, dp); 
    }
    return maxVul;
}


// 使用dp数组(相对于上面方式,浪费内存空间)
int maxSubArray(vector<int>& nums) {
    int maxVul = 0;
    //dp[i]表示nums中以nums[i]结尾的最大子序和
    vector<int> dp(nums.size());                // 一定要分配大小才行
    dp[0] = nums[0];                            // 如果输入是[1]的话,则返回nums[0]
    maxVul = dp[0];
    for (int i = 1; i < nums.size(); i++)       // i从1开始才能有前一项dp[i - 1],且dp[0]已经定义过了
    {
        dp[i] = max(dp[i - 1] + nums[i], nums[i]);      
        maxVul = max(maxVul, dp[i]);
    }

    return maxVul;
}

​编辑

方法3 分治法和贪心法(贪心法感觉类似于dp):

以后有时间研究~