leetcode刷题之旅——53. Maximum Subarray

        本周写的第二道分治算法的题目,因为上次选择的是一道easy的题目,为了提升自己,这次选择了一道middle难度的题目。虽然这道题目是middle的,但是我还是想了很长时间。其实这道题目可以用动态规划直接用O(n)的复杂度来解决,代码也很简单,但是如果想要用分治法就比较难想一点。

        先说一下动态规划的算法。就是初始化max和sum两个变量,一个代表最终的结果最大值,另一个用来选择是加上下一个元素还是直接取值下一个元素。在遍历整个数组时,先取sum+num[i]和num[i]中的较大者,然后赋值给max。这样得到的最终max就是我们想要的结果。如果,sum加上下一个元素仍然没有下一个元素大,那我们就没有必要取下一个元素前的所有元素,如果比下一个元素大,我们就当然要将下一个元素加进来。

        再说一下分治法的算法。我们要分三种情况,第一种是所有元素全部出自于一分为二后的左面的集合,第二种是全部出于右面的集合,还有一种可能性就是出自于左面集合和右面集合。所以我们最后要比较左面子数组最大值、右面子数组最大值和子数组出自于左面集合和左面集合的情况的最大值。前面两个值都很好求,用递归即可。但是最后一种情况怎么求呢,没有什么好办法,采用动态规划的方法从中间向两侧扫描吧。最后,分两部分扫完之后,再相加,就是这种情况的结果。当然这种情况的复杂度为O(nlogn),递推公式是T(n)=2T(n/2)+O(n)。

        分治法其实是把这道题目复杂化了,因为最后一步还是要实现动态规划的过程,索性就开始的时候直接按动态规划的算法扫描整个数组就可以了,没有必要再去求一下left和right。

代码:

class Solution {
public:
    int maxSubArray(vector<int>& nums) 
    {
        return dc(nums,0,nums.size()-1);
    }
    int dc(vector<int>& nums,int begin,int end)
    {
        if(begin==end) return nums[begin];
        int mid=(begin+end)/2;
        int left=dc(nums,begin,mid);
        int right=dc(nums,mid+1,end);
        int sum=nums[mid];
        int leftsum=nums[mid];
        for(int i=mid-1;i>=begin;i--)
        {
            sum+=nums[i];
            if(sum>leftsum) leftsum=sum;
        }
        int rightsum=nums[mid+1];
        sum=nums[mid+1];
        for(int i=mid+2;i<=end;i++)
        {
            sum+=nums[i];
            if(sum>rightsum) rightsum=sum;
        }
        int answer;
        if(left>right) answer=left;
        else answer=right;
        if(answer<(leftsum+rightsum)) answer=leftsum+rightsum;
        return answer;
    }
};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值