连续子数组的最大和【剑指Offer】

连续子数组的最大和

输入一个 非空 整型数组,数组里的数可能为正,也可能为负。

数组中一个或连续的多个整数组成一个子数组。

求所有子数组的和的最大值。

要求时间复杂度为 O(n)。

数据范围
数组长度 [1,1000]。
数组内元素取值范围 [−200,200]。

样例
输入:[1, -2, 3, 10, -4, 7, 2, -5]

输出:18

思路1贪心

贪心策略:

  1. 如果和要变小,那么先取一遍max
  2. 如果临时和t小于0(此时前面的方案已经不可取,对最大和的贡献是负的)那么将t清0

代码1

点击查看代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        bool f = 0;
        int maxn = -300;
        for(int i = 0; i < nums.size(); i ++ ){
            if(nums[i] >= 0)f = 1;	
            maxn = max(maxn,nums[i]);
        }
        int t = 0;
        int ans = 0;
        if(f){
            for(int i = 0; i < nums.size(); i ++ ){
                if(nums[i] < 0)ans = max(ans,t);
                t += nums[i];
                if(t < 0)t = 0;
            }
            ans = max(ans,t);
            return ans;
        }
        else{
            return maxn;
			.//如果全部都是负数,那么最大得到数即为最大和
        }
        
    }
};

思路2dp

定义\(dp[i]\)为前\(i\)项的最大和.\(dp[1]=nums[1]\)
状态转移方程为\(dp[i] = max(dp[i-1]+nums[i],nums[i])\)

代码2

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

代码3滚动数组优化

由于dp数组只用到了i-1,因此可以考虑用滚动数组进行优化

点击查看代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int a = nums[0],ans = nums[0];
        for(auto x:nums){
            a = max(a + x, x);
            ans = max(a,ans);
        }
        return ans;
    }
};
posted @ 2023-03-06 23:26  Keith-  阅读(10)  评论(0编辑  收藏  举报