返回顶部

[leetcode]53. 最大子序和*

53. 最大子序和

Difficulty: 简单

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

示例:

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

进阶:

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

Solution 1.0

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int size = nums.size();
        if(size == 0) return 0;
        vector<int> sum; sum.resize(size);
        sum[0] = nums[0];
        for(int i = 1; i< size; ++i) {
            sum[i] = max(sum[i-1] + nums[i],nums[i]);
        }
        return *max_element(sum.begin(),sum.end());
    }
};

思路

遍历当前数组,如果当前位置之前的全部元素和为正值,则算上当前元素结果必然为最大,否则,如果全部元素和为负数,那么以当前元素作为最大值即可。动归的状态转移方程为

​ dp[i] = nums[i] + (dp[i-1] > 0?dp[i-1]:0)

当然,从递推式可以发现,其实并不需要储存全部元素,只需要前后两个元素即可,因此可以缩小空间复杂度。最终,时间复杂度O(n),空间复杂度O(n)。

Solution 1.1 优化版

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int size = nums.size();
        if(size == 1) return nums[0];
        int pre = nums[0],cur = nums[1],maximum = nums[0];
        for(int i = 1; i < size;++i){
            cur = nums[i] + (pre >= 0 ? pre : 0);
            maximum = max(cur,maximum);
            pre = cur;
        }
        return maximum;
    }
};

思路

减少了空间复杂度。最终,时间复杂度O(n),空间复杂度O(1)。

*Solution 2 分治法

思路

最优解的三种可能:

1.完全在中间位置的左侧

2.完全在中间位置的右侧

3.包含中间位置

posted @ 2020-07-15 21:48  Swetchine  阅读(104)  评论(0编辑  收藏  举报