(C++)Leetcode狂刷200题——标签“数组篇--简单难度10道 #53最大子序和”

第二题 #53 (C++)Leetcode狂刷200题——标签“数组篇--简单难度10道 #53最大子序和”_第1张图片
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-subarray
1、暴力解法 :时间复杂度O(n^2)空间复杂度O(1)
第一遍遍历数组,以每个数组的一个元素为其起始值
第二遍遍历数组,求以某个元素为起始值的最大连续数组和的值
注意:返回的最大值的初始值要设置为INT_MIN

class Solution {
     
public:
    int maxSubArray(vector<int>& nums) {
     
        int max_ans = INT_MIN;
        int nums_size = nums.size();
        for( int i=0; i<nums_size; i++){
     
            int sum = 0;
            for( int j=i; j<nums_size; j++){
     
                sum += nums[j];
                if(sum>max_ans)
                    max_ans = sum;
            }
        }
        return max_ans;
    }
};

2、动态规划法 时间复杂度O(n)、空间复杂度O(n) (优化后使用注释的代码空间复杂度为O(1)
用 f(i)代表以第 i个数结尾的所有连续子数组的最大和,0≤i≤n−1max {f(i)},我们只需要求出每个位置的 f(i),然后返回 f 数组中的最大值即可。我们可以考虑nums[i]单独成为一段还是加入f(i-1)对应的那一段,这取决于nums[i]和 f(i-1)+nums[i] 的大小,所以有f(i) = max { f(i - 1) +nums[i],nums[i]} 。
我们可以只用一个变量 pre 来维护对于当前 f(i)的f(i−1) 的值是多少,从而让空间复杂度降低到 O(1)。

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

        /*
        int pre = 0 ;
        for(const auto &x : nums){
            pre = max( pre + x, x);
            max_ans = max( pre, max_ans);
        }
        */
        return max_ans;
    }
};

3、分治法 递归求最大值:时间复杂度O(nlog(n))、空间复杂度O(log(n))
将数组从中间分开,最大子序一共存在三种情况:
①在数组的左半部分
②在数组的右半部分
③跨域中间节点部分。
然后对分开的数组左右两部分进行递归相同操作。

	class Solution {
     
public:
    int maxSubArray(vector<int>& nums) {
     
        int nums_size = nums.size();
        int ans = INT_MIN;

        ans = maxSubArrayHelper(nums, 0 , nums_size-1);
        return ans;
        
    }

    int maxSubArrayHelper(vector<int>& nums, int left, int right){
     
        
        if(left==right) return nums[left];
        int mid = (left+right)/2;
        int LeftSum = maxSubArrayHelper(nums, left, mid);
        int RightSum  = maxSubArrayHelper(nums, mid+1, right);
        int MidSum = maxSubArrayMid(nums, left, mid, right);

        int result = max(LeftSum,RightSum);
        return max(result,MidSum);
    }

    int maxSubArrayMid(vector<int>& nums, int left, int mid, int right){
     

        int leftSum  = INT_MIN;
        int sums=0;
        for(int i = mid; i >=left; i--){
     
            sums += nums[i];
            leftSum  = max(leftSum ,sums);
        }

        int rightSum  = INT_MIN;
        sums=0;
        for(int i = mid+1; i <=right; i++){
     
            sums += nums[i];
            rightSum = max(rightSum,sums);
        }
        return rightSum+leftSum;
    }
};

4、贪心算法:时间复杂度O(n)空间复杂度O(1)
从数组的左边开始向友遍历迭代,如果累加的和小于0则重新开始累加;

	class Solution {
     
public:
    int maxSubArray(vector<int>& nums) {
     
        int nums_size = nums.size();
        int ans = INT_MIN;
        int sum = 0;

        for(int i = 0; i < nums_size; i++){
     

            sum += nums[i];
            ans = max(sum , ans);
            if(sum<0)
            sum = 0;
        }
        return ans;
        
    }
};

你可能感兴趣的:(leetcode,刷题,leetcode,动态规划,数据结构)