《剑指offer》面试题42. 连续子数组的最大和

问题描述

输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

要求时间复杂度为O(n)。
示例1:

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

提示:

1 <= arr.length <= 10^5
-100 <= arr[i] <= 100

代码

我们定义\(dp[i]\)是以元素\(nums[i]\)结尾的最大和,则更新公式\(dp[i] = max(nums[i],nums[i]+dp[i-1])\)

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int i, n = nums.size(),ans = nums[0];
        vector<int> dp(n);
        dp[0] = nums[0];
        for(i = 1; i < n; ++i)
        {
            dp[i] = max(nums[i],nums[i]+dp[i-1]);
            ans = max(dp[i],ans); 
        }
        return ans;
    }
};

结果

执行用时 :52 ms, 在所有 C++ 提交中击败了25.93%的用户
内存消耗 :23.8 MB, 在所有 C++ 提交中击败了100.00%的用户

代码

当然我们也可以把空间复杂度降为\(O(1)\),根据上面的更新公式,显然:

\[dp[i] = \begin{cases} dp[i-1]+nums[i],&dp[i-1]>0\\ nums[i],&dp[i-1]\leq 0 \end{cases} \]

因此我们可以直接在\(nums\)上直接修改

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int i, n = nums.size(),ans = nums[0];
        for(i = 1; i < n; ++i)
        {
            nums[i] += max(0,nums[i-1]);
            ans = max(nums[i],ans); 
        }
        return ans;
    }
};

结果:

执行用时 :44 ms, 在所有 C++ 提交中击败了42.46%的用户
内存消耗 :22.9 MB, 在所有 C++ 提交中击败了100.00%的用户
posted @ 2020-04-20 09:45  曲径通霄  阅读(93)  评论(0编辑  收藏  举报