LeetCode 53.Maximum Subarray

1.题目

2.题意

求最大子序列,follow up要求采用分治法

3.我的解法

int maxSubArray(int* nums, int numsSize) {
    int ans=nums[0],i,sum=0;
    for (i=0;i<numsSize;i++){
        sum+=nums[i];
        if(ans<sum)ans=sum;
        if(sum<0)sum=0;
    }
    return ans;
}

优于100%

4.优秀解法

Kadane's Algorithm

该算法的思想就是,一个最大的子序列一定是这样的:当进入一个新的值时,判断一下这个值与之前的元素和

大小关系,如果这个值更大,说明之前的元素和没有意义,应该抛弃不用,直接从这个值开始,这样一个

判断就确定了目前的最大值即,不是当前一个值就是之前元素和加上这个值。

而对于全局的最大值,就要每次来比较当前的最大值,把当前的最大值中真正最大的保留下来,也就是最后的

结果,这实际上是一种动态规划DP

int maxSubArray(int* nums, int numsSize) {
    
    int maxSum = nums[0];
    int sum = maxSum;
    for(int i = 1; i < numsSize; i++){
        
        sum += nums[i];
        if (sum > maxSum) {
            maxSum = sum;
        }
        
        if (sum < nums[i]) {
            sum = nums[i];
        }
        if (maxSum < nums[i]) {
            maxSum = nums[i];
            sum = nums[i];
        }
    }
    
    return maxSum;
}

c++的形式看的更直观

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

在本题中分治法的复杂程度更高,为nlogn,高于n,所以在这里只讨论一下分治法的大致思路

一个最大子序列有三种情况,要么在左半边,要么在右半边,要么跨越中线

先考虑在两边的情况,以左半边为例,右半边类似

递归的进行,缩小问题的规模,问题实际上又变成了一个只含左半边元素的,求最大子序列问题,所以左右进行递归即可

问题的最后都会变成求跨越中线的情况,这个情况就需要首先从中心开始,向两边延伸,先左后右,只要保证包含中点即可

最后得到最大的子序列,开始递归返回。分治法DC

class Solution {
public: 
    int maxSubArray(vector<int>& nums) {
        int n = nums.size();
        return maxSub(nums, 0, n - 1);
    }
private:
    int maxSub(vector<int>& nums, int l, int r) {
        if (l > r) return INT_MIN;
        int m = l + ((r - l) >> 1);
        int lm = maxSub(nums, l, m - 1); // left half
        int rm = maxSub(nums, m + 1, r); // right half
        int i, sum, ml = 0, mr = 0;
        // Move leftwards
        for (i = m - 1, sum = 0; i >= l; i--) {
            sum += nums[i];
            ml = max(sum, ml);
        }
        // Move rightwards
        for (i = m + 1, sum = 0; i <= r; i++) {
            sum += nums[i];
            mr = max(sum, mr);
        }
        return max(ml + mr + nums[m], max(lm, rm));
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值