【LEETCODE】#53 最大子序和(在线处理法&分而治之法)

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

示例:

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

进阶:

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

1.在线处理法

执行用时 : 24 ms, 在Maximum Subarray的C++提交中击败了15.31% 的用户

内存消耗 : 10.3 MB, 在Maximum Subarray的C++提交中击败了0.94% 的用户

/*第一种写法*/
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int ThisSum=0,MaxSum=0;
        int i;
        int cnt=0;
        for(i=0;i<nums.size();i++){
            ThisSum+=nums[i];
            if(ThisSum>MaxSum)MaxSum=ThisSum;
            if(ThisSum<0){
                ThisSum=0;
                cnt++;
            }
        }
        if(cnt==nums.size()){    //当nums全为负时,需要找出一个最大的负数
            for(i=0,MaxSum=nums[0];i<nums.size();i++)
                if(nums[i]>MaxSum)MaxSum=nums[i];
        }
        return MaxSum;
    }
};
/*第二种写法*/
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int thisSum=0,maxSum=0;
        int maxNum=INT_MIN;
        for(int i=0; i<nums.size(); i++) {
            thisSum+=nums[i];
            maxNum=max(maxNum,nums[i]);
            if(thisSum>maxSum) maxSum=thisSum;
            if(thisSum<0) thisSum=0;
        }
        if(maxNum<0) return maxNum;
        else return maxSum;
    }
};

2.分而治之法

执行用时 : 24 ms, 在Maximum Subarray的C++提交中击败了15.31% 的用户

内存消耗 : 10.4 MB, 在Maximum Subarray的C++提交中击败了0.94% 的用户

class Solution {
public:
    int Divide(vector<int>& nums,int left,int right){    //分治函数
        int MaxLeft,MaxRight,MaxMiddle;
        int center;
        center=(left+right)/2;
        
        if(left==right){        //停止递归
            return (nums[left]>0)?(nums[left]):0;
        }
        
        MaxLeft=Divide(nums,left,center);            //center左侧的最大序列和
        MaxRight=Divide(nums,center+1,right);        //center右侧的最大序列和
        int i;
        int ThisSum=0,MaxSumL=0,MaxSumR=0;           //跨center的最大序列和
        for(ThisSum=0,i=center;i>=left;i--){
            ThisSum+=nums[i];
            if(ThisSum>MaxSumL)MaxSumL=ThisSum;
        }
        for(ThisSum=0,i=center+1;i<=right;i++){
            ThisSum+=nums[i];
            if(ThisSum>MaxSumR)MaxSumR=ThisSum;
        }
        MaxMiddle=MaxSumL+MaxSumR;
        //返回center左侧、center右侧、跨center序列和中三者最大值
        return (MaxLeft>MaxMiddle)?(MaxLeft>MaxRight?MaxLeft:MaxRight):(MaxMiddle>MaxRight?MaxMiddle:MaxRight);
    }
public:
    int maxSubArray(vector<int>& nums) {
        int max=Divide(nums,0,nums.size()-1);
        if(max!=0)return max;
        else{            //max==0时,证明序列全负数,重新遍历寻找最大的负数
            int i;
            for(max=nums[0],i=0;i<nums.size();i++){
                if(max<nums[i])max=nums[i];
            }
            return max;
        }
    }
};

【后记】

1.这是当初学习数据结构第一节课时学到的题呢,然而这次做还是偷偷看了答案。。。

展开阅读全文

没有更多推荐了,返回首页